21

是否可以编写一个函数arity :: a -> Integer来确定任意函数的数量,使得

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

?

4

6 回答 6

26

是的,它可以非常非常容易地完成:

arity :: (a -> b) -> Int
arity = const 1

基本原理:如果它是一个函数,您可以将它应用于恰好 1 个参数。f a b请注意,haskell 语法无法按原样应用于 0、2 或更多参数(f a) b,即 not f applied to a and b, but (f applied to a) applied to b。当然,结果可能是另一个可以再次应用的函数,等等。

听起来很愚蠢,但事实就是如此。

于 2011-12-03T17:57:15.207 回答
18

这很容易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) 

更新发现问题。您需要为多态函数指定非多态类型:

arity (foldr :: (a -> Int -> Int) -> Int -> [a] -> Int)

还不知道如何解决这个问题。

正如 Sjoerd Visscher 在下面评论的那样, Upd2 “您必须指定非多态类型,因为答案取决于您选择的类型”。

于 2011-12-03T16:55:13.607 回答
11

如果id有arity 1,不应该id x有arity 0?但是,例如,id map与 相同map,在您的示例中将具有 2 个值。

以下功能是否具有相同的数量?

f1 = (+)
f2 = (\x y -> x + y)
f3 x y = x + y

我认为你对“arity”的概念没有很好的定义......

于 2011-12-03T16:43:11.867 回答
3

在 Haskell 中,每个“函数”都只有一个参数。看起来像“多参数”的函数实际上是一个接受一个参数并返回另一个接受其余参数的函数的函数。所以从这个意义上说,所有函数都有 arity 1。

于 2011-12-03T21:27:21.413 回答
2

使用标准 Haskell 是不可能的。可以使用 IncoherentInstances 或类似的扩展。

但是你为什么要这样做呢?你不能问一个函数它需要多少个参数,然后使用这些知识来精确地给它那个数量的参数。(除非您使用的是 Template Haskell,在这种情况下,是的,我希望它在编译时是可能的。您使用的是 Template Haskell 吗?)

您要解决的实际问题是什么?

于 2011-12-03T16:42:42.997 回答
1

这个怎么样:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
于 2011-12-05T07:46:55.750 回答