我试图了解Haskell中以下2个lambda表达式的含义:
f = \x -> x (\y -> x y)
g = \x -> (\y -> y) x
我试图转换它们,我得到了:
f x y = x x y
g x y = y x
这是正确的吗?我假设两个函数的参数都必须是x和y,因为它们都可以在函数描述的lambda表达式中找到。我基本上是这样理解的:f(x)= x f(y)和f(y)= y x。对于g,g(x)= g(y)x和g(y)= y。但是,由于我是Haskell的新手,所以我对这些类型的转换不是很自信。如果不正确,什么是正确的转换?
答案 0 :(得分:5)
都不正确。您的解决方案使用功能
f x y = x x y
g x y = y x
这实际上是
f = \x -> (\y -> x x y)
g = \x -> (\y -> y x)
与原始表达方式不同
f = \x -> x (\y -> x y)
g = \x -> (\y -> y) x
以上两个等式可以重写为
f x = x (\y -> x y)
g x = (\y -> y) x
但是从这里开始,没有办法将其余的lambda转化为f
或g
的更多参数。充其量,我们可以使用beta / eta转换来简化它们并获取
f x = x x -- eta (\y -> x y) = x
g x = x -- beta (\y -> y) x = x
(另请参阅Will Ness的以下评论,他指出,通过在f
中进行额外的eta扩展,我们可以达到OP的定义。但这仍然是偶然的。)
最后,请注意,Haskell将不会接受f x = x x
,因为它不能被键入,除非我们使用等级2类型并显式提供f :: (forall a. a) -> b
之类的类型注释。原始代码f = \x -> x (\y -> x y)
遇到相同的问题。在无类型语言中也可以,例如编程语言理论中的无类型lambda演算。
答案 1 :(得分:1)
GHCi提示符下的:type
命令是您的朋友。让我们先来看第二个例子
λ> :type let g = \x -> (\y -> y) x in g
let g = \x -> (\y -> y) x in g :: p -> p
因此g
的类型正确,并且是编写身份函数:: p -> p
的复杂方法。具体来说,g
取一些x
并将身份函数(\y -> y)
应用于x
,从而得到x
。 GHCi在给定类型时使用新鲜的类型名称p
,以避免造成混淆。没有您的g x y = ...
不相等。 (使用:type
进行检查。)
您可以将:type
缩写为:t
。然后,让我们举个第一个例子。
λ> :t let f = \x -> x (\y -> x y) in f
* Occurs check: cannot construct the infinite type: t2 ~ t2 -> t3
* In the first argument of `x', namely `(\ y -> x y)'
In the expression: x (\ y -> x y)
In the expression: \ x -> x (\ y -> x y)
* Relevant bindings include
x :: t2 -> t3 (bound at <interactive>:1:10)
f :: (t2 -> t3) -> t3 (bound at <interactive>:1:5)
Errk。您建议的f
是否与此相同?
λ> :t let f x y = x x y in f
* Occurs check: cannot construct the infinite type:
t3 ~ t3 -> t4 -> t5
* In the first argument of `x', namely `x'
它至少看起来像是类似的错误消息。这些t2, t3, t4, t5
是什么?再次,它的GHCi使用了新鲜的名称作为类型,以避免混淆。
通过查看let f = ...
,GHCi看到x
被应用于某事物,因此它给出了x :: t2 -> t3
,其中t2
是其自变量的类型,t3
是返回类型。它还显示f = \x -> x (blah)
。因此,f
的返回类型必须为x
返回的值,即t3
,并且f
的参数为x
。 f :: (t2 -> t3) -> t3
。
在(blah)
内,有x
应用于某物。因此,事物(即y
)必须是x
的参数类型,返回类型必须是x
的返回类型。即(\y -> x y) :: t2 -> t3
。 Errk:那么我们必须具有x
的自变量类型,因为x
被应用于它。而我们写“与”相同的方法就是使用~
。
然后错误消息告诉您GHCi试图理解t2 ~ (t2 -> t3)
。 (->
比~
绑定更紧密。)而且,如果您尝试将t2
的等效项替换为RHS,则会无限地获得t2 ~ (((... -> t3) -> t3)-> t3)
的广告。
您建议的f x y =
等效项不是等效项(消息/键入略有不同)。但是它们都是无限类型,所以不允许。