Haskell: Function to determine the arity of functions?

血红的双手。 提交于 2019-12-04 08:56:33

问题


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

> arity map
2
> arity foldr
3
> arity id
1
> arity "hello"
0

?


回答1:


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




回答2:


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.




回答3:


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




回答4:


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.




回答5:


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?




回答6:


How about this:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0


来源:https://stackoverflow.com/questions/8369114/haskell-function-to-determine-the-arity-of-functions

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