Haskell:确定函数数量的函数?

发布于 2024-12-19 12:02:29 字数 176 浏览 5 评论 0原文

是否可以写一个函数 arity :: a -> Integer 确定任意函数的数量,这样

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

?

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

?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦幻的心爱 2024-12-26 12:02:29

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

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

原理:如果它是一个函数,您可以将它应用于恰好 1 个参数。请注意,haskell 语法使得不可能应用于 0、2 个或更多参数,因为 fa b 实际上是 (fa) b,即不将 f 应用于 a 和b,但(f应用于a)应用于b
当然,结果可能是另一个可以再次应用的函数,等等。

听起来很愚蠢,但这只是事实。

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.

清风疏影 2024-12-26 12:02:29

使用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发现问题。您需要为多态函数指定非多态类型:

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

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

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

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

粉红×色少女 2024-12-26 12:02:29

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

以下函数的数量相同吗?

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

我认为您对“数量”的概念没有明确定义......

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

眉黛浅 2024-12-26 12:02:29

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

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.

祁梦 2024-12-26 12:02:29

对于标准 Haskell 来说这是不可能的。可以使用 IncoherentInstances 或类似的扩展。

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

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

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?

小苏打饼 2024-12-26 12:02:29

这个怎么样:

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

How about this:

arity :: a -> Int
arity (b->c) = 1 + arity (c)
arity _ = 0
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文