我试图使用匹配类型在 Dotty 中实现SKI 组合器演算。
SKI 组合微积分的简要说明:
S,K, 和I是项(xy)is an term ifxandyare 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)