Haskell: Function to determine the arity of functions?

后端 未结 6 616
一个人的身影
一个人的身影 2021-02-05 07:00

Is it possible to write a function arity :: a -> Integer to determine the arity of arbitrary functions, such that

> arity map
2
> arity fol         


        
相关标签:
6条回答
  • 2021-02-05 07:05

    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.

    0 讨论(0)
  • 2021-02-05 07:08

    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.

    0 讨论(0)
  • 2021-02-05 07:15

    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?

    0 讨论(0)
  • 2021-02-05 07:15

    How about this:

    arity :: a -> Int
    arity (b->c) = 1 + arity (c)
    arity _ = 0
    
    0 讨论(0)
  • 2021-02-05 07:19

    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".

    0 讨论(0)
  • 2021-02-05 07:26

    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...

    0 讨论(0)
提交回复
热议问题