我试图使用匹配类型在 Dotty 中实现SKI 组合器演算。
SKI 组合微积分的简要说明:
S
,K
, 和I
是项(xy)
is an term ifx
andy
are terms and is like 函数应用(((Sx)y)z)
(same asSxyz
) 返回xz(yz)
(same as(xz)(yz)
)((Kx)y)
(相同Kxy
)返回x
(Ix)
返回x
以下是我使用R
的(尽可能减少术语)。一个术语(xy)
被写成一个元组(x,y)
, 和S
, K
, 和I
是特征。
trait S
trait K
trait I
type R[T] = T match {
case (((S,x),y),z) => R[((x,z),(y,z))]
case ((K,x),y) => R[x]
case (I,x) => R[x]
case (a,b) => R[a] match {
case `a` => (a, R[b])
case _ => R[(R[a], R[b])]
}
case T => T
}
但是,以下 2 行无法编译(出于相同的原因)(Scastie):
val check: (K, K) = ??? : R[(((S,I),I),K)]
val check2: (K, K) = ??? : R[((I,K),(I,K))]
该错误说它需要(K,K)
但找到R[((I, K), (I, K))]
。我希望它首先看到 S 并将其变成(IK)(IK)
,或者R[((I,K),(I,K))]
,之后它应该匹配第一个的评估(I, K)
并看到它是K
,这与(I, K)
使其返回R[(R[(I,K)], R[(I,K)])]
,它成为R[(K,K)]
,它成为正义(K,K)
。
然而,它并没有超越R[((I,K),(I,K))]
。显然,如果它是嵌套的,它不会减少术语。这很奇怪,因为我尝试了相同的方法,但使用了实际的运行时函数,而且它似乎工作正常(Scastie)。
case object S
case object K
case object I
def r(t: Any): Any = t match {
case (((S,x),y),z) => r(((x,z),(y,z)))
case ((K,x),y) => r(x)
case (I,x) => r(x)
case (a,b) => r(a) match {
case `a` => (a, r(b))
case c => (c, r(b))
}
case _ => t
}
正如预期的那样,来自println(r((((S, I), I), K)))
的输出。(K,K)
有趣的是,删除它的规则K
让它可以编译,但它不能识别(K, K)
和R[(K, K)]
作为同一类型。也许这就是导致问题的原因?(斯卡斯蒂)
def check2: (K, K) = ??? : R[(K, K)]
//Found: R[(K, K)]
//Required: (K, K)