Is there a general way to tell the number of parameters of a function in Haskell?

若如初见. 提交于 2019-12-05 13:04:11

Just an idea; you can tell the number of parameters of a function at value level with the following code.

https://gist.github.com/nushio3/5867066

import Data.Typeable
import Test.Hspec

arityOf :: Typeable a => a -> Int
arityOf x = go $ typeOf x
  where
    go tr
      | isFun $ typeRepTyCon tr = 1 + go (last $ snd $ splitTyConApp tr)
      | otherwise               = 0

    funTyCon = typeRepTyCon $ typeOf ((1+):: Int -> Int)
    isFun = (funTyCon ==)

main :: IO ()
main = hspec spec

func :: (Int -> Int) -> Int -> Int
func = undefined

spec :: Spec
spec = describe "arityOf" $ do
  it "evaluates Integers correctly" $ arityOf (1::Int) `shouldBe` 0
  it "evaluates Strings correctly" $ arityOf "(1::Int)" `shouldBe` 0
  it "evaluates monads correctly" $ arityOf main `shouldBe` 0
  it "evaluates multiplications correctly" $ arityOf ((*) :: Int -> Int -> Int)
    `shouldBe` 2
  it "is not deceived by non-tail argument" $ arityOf func `shouldBe` 2

I found one way with type families, which works in GHC 7.6.1. It is a bit of a hack, though, since the problem of deciding what is the "ending type" is solved by marking it with a wrapper:

-- requires GHC.TypeLits, DataKinds, TypeFamilies and so on
newtype V a = V { unV :: a }

type family GetF f :: Nat
type instance GetF (V s) = 0
type instance GetF (a -> b) = 1 + (GetF b)

data Forget (x :: k) -- for showing types of kind Nat

which gives

*Main> :t undefined :: Forget (GetF (Int -> (Char -> Char -> V Bool)))
undefined :: Forget (GetF (Int -> (Char -> Char -> V Bool)))
  :: Forget Nat (1 + (1 + (1 + 0)))

But I think the problem could really be solved with closed type families, which seem to come up in one of the next versions. Now, I've just read about their existence in the given link, but

type family GetF' f :: Nat where
  GetF' (a -> b) = 1 + (GetF' b)
  GetF' a = 0

looks like it should work. True pattern matching on types, finally! (And if this is nonsense, I would be really interested in some more explanation about them.)

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!