我正在尝试理解函数的 Haskell 类型变量。我写了一个函数:
applyTwice f x = f(f x)
我试图理解这个函数的类型变量,所以我做了一个:t applyTwice
。这是 Haskell 解释类型的方式:
applyTwice :: (t -> t) -> t -> t
然后我创建了另一个函数:
applyOnce f x = f x
这次 :t
Haskell 返回
applyOnce :: (t1 -> t) -> t1 -> t
我的问题是
我们如何阅读/理解这些函数接受和返回的内容?
这适用于
applyTwice
。如果他们说->
的左侧是函数接受的内容,而右侧是返回的内容,那么它不应该是applyTwice::((t -> t) -> t) -> t
?(t -> t)
为(f x)
和((t -> t) -> t)
为f (f x )
并且返回类型为t
。- 这是用于
applyOnce
。为什么函数的类型被解释为applyOnce::(t1 -> t) -> t1 -> t
?因为我们只接受一个函数并返回它的值。不应该是applyOnce::(t1 -> t) -> t1
吗?
作为 Haskell 的初学者,我希望得到这方面的任何建议。
最佳答案
我们有:
applyTwice f x = f(f x)
只有当 x
和 f x
的类型相同时,这才有意义(否则你如何能够将 f x
传递给接受 x
的函数?)。因此,您可以说 applyTwice
接受 2 个输入参数:
- 接受类型 t 并返回相同类型 t 的函数
- 某种类型的输入
现在这个输入可以是任何类型,比如 t1。但是您还必须能够将函数应用于此输入,因此输入的类型也必须是 t。放在一起,我们得到签名:
applyTwice :: (t -> t) -> t -> t
请记住,只有最后一项是返回类型,所有其他项都是输入类型。
现在考虑:
applyOnce f x = f x
简单地说,关于函数 f 的全部内容就是它应该能够接受任何类型的输入 x。没有关于函数应该返回什么类型的信息except applyOnce
也应该返回相同的类型。因此,我们最终得到了您看到的签名:
applyOnce :: (t1 -> t) -> t1 -> t
其中 t1 可以是任何类型,t 可以是任何类型(与 t1 相同或不同),但要求 f
的返回类型匹配 applyOnce
,这里用 t 表示。
TL;DR:具有 n 个输入的函数的函数签名将始终具有 (n+1) 项,最后一项将是函数的返回类型。
但是,您应该注意,这实际上并不是事情在幕后的运作方式。 Haskell 中的所有函数实际上都接受一个参数,即它们是curried。您可以阅读更多相关信息 here .
关于Haskell 函数类型说明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42243902/