I can tell the number of parameters of a function with the following code
{-#Language MultiParamTypeClasses#-}
{-#Language FunctionalDependencies#-}
{-#Language UndecidableInstances#-}
data Zero
data Succ a
class Number a
instance Number Zero
instance (Number a) => Number (Succ a)
class NotFunction a
instance NotFunction Int
instance NotFunction Float
instance NotFunction (IO a)
class (Number n) => FunctionLevel f n | f -> n where
functionLevel :: f -> n
instance FunctionLevel Int Zero where
functionLevel = undefined
instance FunctionLevel Float Zero where
functionLevel = undefined
instance FunctionLevel (IO a) Zero where
functionLevel = undefined
instance FunctionLevel Double Zero where
functionLevel = undefined
instance (FunctionLevel f' n) => FunctionLevel (a->f') (Succ n) where
functionLevel = undefined
And we get:
*Main> :t functionLevel (undefined::a->b->Int)
functionLevel (undefined::a->b->Int) :: Succ (Succ Zero)
*Main> :t functionLevel (undefined::a->b->Double)
functionLevel (undefined::a->b->Double) :: Succ (Succ Zero)
*Main> :t functionLevel (undefined::a->b->c->d->IO a)
functionLevel (undefined::a->b->c->d->IO a)
:: Succ (Succ (Succ (Succ Zero)))
*Main> :t functionLevel (undefined::a->b->c->d->Int)
functionLevel (undefined::a->b->c->d->Int)
:: Succ (Succ (Succ (Succ Zero)))
As you can see, functionLevel
performs just as we expected for functions "ended" with some special types. My question is: could we generalize this to tell parameter number of an arbitrary function?