Haskell:确定函数arity的函数?

时间:2011-12-03 16:32:55

标签: haskell introspection arity

是否可以编写函数arity :: a -> Integer来确定任意函数的arity,例如

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

6 个答案:

答案 0 :(得分:25)

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

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

基本原理:如果它是一个函数,你可以将它应用于1个参数。请注意,haskell语法使得无法应用于0个,2个或更多个参数,因为f a b实际上是(f a) b,即不是f applied to a and b,而是(f applied to a) applied to b。 当然,结果可能是可以再次应用的另一个功能,等等。

听起来很愚蠢,但事实并非如此。

答案 1 :(得分: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)

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

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

答案 2 :(得分:11)

如果id有arity 1,那么id x不应该有arity 0吗?但是,例如,id mapmap相同,在您的示例中将为{2}。

让以下功能相同吗?

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

我认为你的“arity”概念没有明确界定......

答案 3 :(得分:3)

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

答案 4 :(得分:2)

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

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

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

答案 5 :(得分:1)

这个怎么样:

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