Haskell中的零阶函数

4

我开始学习Haskell,并尝试指定一个具有Int类型的任意零阶函数的Haskell类型签名。就我所知,对于一阶函数,它应该类似于 k :: Int -> Int。那么零阶函数的类型签名是否只是 k :: Int,或者这样假设是错误的?谢谢!

2个回答

5
在Haskell中没有“零阶”函数。每个函数在Haskell中都有一个参数的数量,即 1 :每个函数接受一个参数,并返回一个值。返回值本身可以是另一个函数。(其参数和/或返回类型为函数类型的函数称为高阶函数。) k :: Int 不是一个函数;它只是一个Int 。
在Haskell中最接近具有0个参数的函数是一种类型为() -> a 的函数,其中a是某种类型。因为只有一种类型()的值,所以只有一种调用该函数的方法:使用()。
k :: () -> Int
k () = 3

(您可能会注意到,对于类型为 a 的每个值,恰好有一个类型为 () -> a 的函数;这是一些理论上的重要性问题,但它并不真正与此处的问题相关。)

3
返回的类型本身是一个函数的函数不是高阶函数。 - Daniel Wagner
1
当然是的。https://wiki.haskell.org/Higher_order_function - chepner
3
哇,虽然现在我同意多个地方对这个定义的看法,但是相比我之前以为的,它真的是一个毫无用处的定义。你会告诉我有人认为 (&&) 是一种奇特的对象、一种高阶函数吗? - Daniel Wagner
1
我也认同这个观点。t1 -> t2 -> t3 不属于 (t1 -> t2) -> t3 的形式,而高阶函数则是类型为 (t1 -> t2) -> t3 的值。在数学中,通常会以“X是Y”的形式定义一个概念,而不需要列出X不是的所有情况。 - Daniel Wagner
5
这是“higher order”的历史数学定义,但在 Haskell 中我们实际上不再这样使用,因为柯里化是常态。非正式地说,如果一个函数同构于一个n阶函数,我们就称其为“n阶”函数;同理,“n元”也是这样。这些区别在范畴论中很重要:使用笛卡尔闭包后,您可以将“function”箭头内部化为“closure”对象(指数项)。函数 f : A × B → Cf(a, —) : B → C 中是部分应用的,而 g : A → C^B完全应用的,以 g a : C^B 形式(“分配”一个闭包)。在 Haskell 中它们都被称为 (->) - Jon Purdy
显示剩余4条评论

5
有一些关于 Haskell 的信仰,从“Haskell 中的每个函数都恰好有一个参数”开始。这些信仰是 有用的 :它们形成了非常精确的谈论 Haskell 和理解 Haskell 行为的基础。
但它们总是有点太强硬了,尽管 -> 类型的构造器是二元的,因此从技术上讲,函数具有一个参数和一个返回类型,但我认为在谈论和思考 Haskell 时也很有用,可以使用缩写“带有两个参数的函数”来统一表示类型如a -> (b -> c)。显然,继续推广 arity 以计算箭头类型右侧需要多少次才能到达非箭头类型,这样 a -> (b -> c) 具有 arity 2,Bool -> Bool -> Bool -> Bool 具有 arity 3,而 Int 具有 arity 0。这样定义没有问题。
如果您允许自己这种灵活性,那么您还可以更加灵活地讨论顺序,自然的“顺序”的概念是,在不得不在非箭头类型结束时向左移动多少次之前,您可以向左移动多少次。因此,Bool -> Bool 具有顺序 1,(a -> b) -> [a] -> [b] 具有顺序 2(并且 arity 为 2),((Int -> r) -> r) -> Cont r Int 具有顺序 3…在允许自己这种灵活性的世界中,我认为自然地将 Int 视为顺序-0,arity-0 的函数是 非常自然的。(实际上,可以推导出所有顺序-0 函数都具有 arity-0。)

1
它不能应用于类型变量,因为 a -> a 的顺序取决于如何实例化 a - Iceland_jack
2
@Iceland_jack 是的,在存在多态性的情况下必须小心处理。不过这并非不可克服;对于大多数情况来说,采用简单方法并将变量视为非函数即可。 - Daniel Wagner
@Iceland_jack 重要的是,id不能将其参数用作函数,这正是因为它是多态的。因此,我们从它的类型中知道它不能“做高阶事情”,这在某种程度上证明了简单地说它不是高阶的是有道理的。 - Ben
1
个人而言,我更喜欢保持“函数是类型为A->B的东西”。我宁愿将元数的概念推广到非函数事物上,以便说“Int的元数为零”,而不是说“Int是一个元数为零的函数”。我仍然希望有一个词来表示可以应用于参数以计算某些东西的事物。如果“函数”被重新定义为包括元数为零的值,则它将包括所有 Haskell 值,而我们已经有一个词来表示这个:值。 - Ben

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接