Is it possible to write a function arity :: a -> Integer
to determine the arity of arbitrary functions, such that
> arity map
2
> arity fol
In Haskell, every "function" takes exactly one argument. What looks like a "multi-argument" function is actually a function that takes one argument and returns another function which takes the rest of the arguments. So in that sense all functions have arity 1.
Yes, it can be done very, very easily:
arity :: (a -> b) -> Int
arity = const 1
Rationale: If it is a function, you can apply it to exactly 1 argument. Note that haskell syntax makes it impossible to apply to 0, 2 or more arguments as f a b
is really (f a) b
, i.e. not f applied to a and b
, but (f applied to a) applied to b
.
The result may, of course, be another function that can be applied again, and so forth.
Sounds stupid, but is nothing but the truth.
It's not possible with standard Haskell. It may be possible using the IncoherentInstances or similar extension.
But why do you want to do this? You can't ask a function how many arguments it expects and then use this knowledge to give it precisely that number of arguments. (Unless you're using Template Haskell, in which case, yes, I expect it is possible at compile time. Are you using Template Haskell?)
What's your actual problem that you're trying to solve?
How about this:
arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
It's easy with OverlappingInstances
:
{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}
class Arity f where
arity :: f -> Int
instance Arity x where
arity _ = 0
instance Arity f => Arity ((->) a f) where
arity f = 1 + arity (f undefined)
Upd Found problem. You need to specify non-polymorphic type for polymorphic functions:
arity (foldr :: (a -> Int -> Int) -> Int -> [a] -> Int)
Don't know how to solve this yet.
Upd2 as Sjoerd Visscher commented below "you have to specify a non-polymorphic type, as the answer depends on which type you choose".
If id
has arity 1, shouldn't id x
have arity 0? But, for example, id map
is identical to map
, which would has arity 2 in your example.
Have the following functions the same arity?
f1 = (+)
f2 = (\x y -> x + y)
f3 x y = x + y
I think your notion of "arity" is not well defined...