请注意,您编写的不是Y
组合器的实现。“Y
组合子”是 λ 演算中的特定“定点组合子”。一个术语的“不动点”g
就是这样一个点x
,
g(x) = x
“定点组合器”F
是可用于“产生”固定点的术语。也就是说,这样,
g(F(g)) = F(g)
该术语Y = λf.(λx.f (x x)) (λx.f (x x))
是服从该等式的众多术语之一,即它g(Y(g)) = Y(g)
在某种意义上可以将一个术语简化为另一个术语。此属性意味着此类术语,包括Y
可用于在微积分中“编码递归”。
关于打字注意,Y
组合子不能在简单类型的 λ-演算中输入。甚至在系统 F 的多态微积分中也没有。如果你尝试输入它,你会得到一种“无限深度”。要键入它,您需要在类型级别进行递归。因此,如果您想将例如简单类型的 λ-演算扩展为您Y
作为原语提供的小型函数式编程语言。
不过,您没有使用 λ-演算,而且您的语言已经带有递归。所以你写的是Scala中定点“组合器”的简单定义。直截了当,因为定点(几乎)紧跟定义。
Y(f)(x) = f(Y(f))(x)
对所有人都是正确的x
(它是一个纯函数),因此,
Y(f) = f(Y(f))
这是定点方程。关于类型的推断Y
考虑方程Y(f)(x) = f(Y(f))(x)
并让,
f : A => B
Y : C => D
因为作为输入然后Y : C => D
,f : A => B
C = A => B
因为Y f : D
是f : A => B
then的输入
D = A
并且由于输出与那时Y f : D
相同f(Y(f)) : B
D = B
到目前为止,我们有,
Y : (A => A) => A
因为Y(f)
应用于x
,Y(f)
是一个函数,所以
A = A1 => B1
对于某些类型A1
,B1
因此,
Y : ((A1 => B1) => (A1 => B1)) => A1 => B1