简体   繁体   English

Haskell:确定函数arity的函数?

[英]Haskell: Function to determine the arity of functions?

Is it possible to write a function arity :: a -> Integer to determine the arity of arbitrary functions, such that 是否可以编写一个函数arity :: a -> Integer来确定任意函数的arity,这样就可以了

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

?

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. 基本原理:如果它是一个函数,你可以将它应用于1个参数。 Note that haskell syntax makes it impossible to apply to 0, 2 or more arguments as fab is really (fa) b , ie not f applied to a and b , but (f applied to a) applied to b . 请注意,haskell语法使得无法应用于0,2或更多参数,因为fab实际上是(fa) b ,即不f applied to a and b ,但是(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. 听起来很愚蠢,但事实并非如此。

It's easy with OverlappingInstances : 使用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. Upd Found问题。 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". 作为Sjoerd Visscher的Upd2在下面评论说“你必须指定一个非多态的类型,因为答案取决于你选择的类型”。

If id has arity 1, shouldn't id x have arity 0? 如果id有arity 1,那么id x不应该是arity 0吗? But, for example, id map is identical to map , which would has arity 2 in your example. 但是,例如, id map是相同的map ,这将在你的榜样元数2。

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... 我认为你的“arity”概念没有明确定义......

In Haskell, every "function" takes exactly one argument. 在Haskell中,每个“函数”只需要一个参数。 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. 所以在这个意义上所有功能都有arity 1。

It's not possible with standard Haskell. 使用标准Haskell是不可能的。 It may be possible using the IncoherentInstances or similar extension. 可以使用IncoherentInstances或类似的扩展。

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?) (除非你使用的是模板Haskell,在这种情况下,是的,我希望它可以在编译时使用。你使用的是模板Haskell吗?)

What's your actual problem that you're trying to solve? 您试图解决的实际问题是什么?

How about this: 这个怎么样:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM