我正在尝试在 scala 中对组合微积分进行非常轻量级的编码。最初,我只是实现 S 和 K 组合器、应用程序和常量值。后来我希望提升 scala 函数并允许将表达式评估为 scala 函数。不过,那是以后的事了。这是我到目前为止所拥有的。
/** Combinator expression */
sealed abstract class CE
/** Application: CE| (x y) <=> LC| (x:(A=>B) y:A) : B */
case class Ap[A <: CE, B <: CE, X](e1: A, e2: B) extends CE
/** A raw value with type */
case class Value[T](v: T) extends CE
/** Some combinator */
sealed abstract class Comb extends CE
/** The S combinator: CE| S x y z
* LC| λx:(A=>B=>C).λy:(A=>B).λz:A.(x z (y z)) : C
* S : ∀A.∀B.∀C. (A => B => C) => (A => B) => A => C
*/
case object S extends Comb
/** The K combinator: CE| K x y
* LC| λx:A.λy:B.x:A : A
* K : ∀A => ∀B => A
*/
case object K extends Comb
现在我想对此做一些类型推断。为了简单地实现小步和大步减少,数据模型是无类型的,所以我希望类型在这个结构之外。让我们介绍一些东西来保存类型信息。
trait TypeOf { type typeOf }
值类型很简单。
implicit def typeOfValue[T](vt: Value[T]) : TypeOf =
new TypeOf { type typeOf = T }
应用有点棘手,但基本上归结为功能应用。让我们为组合应用程序引入一个类型 ⊃,以避免与普通的 scala 应用程序混淆。
/** Combinator application */
class ⊃[+S, -T]
implicit def typeOfAp[Ap[A, B], A <: CE, B <: CE], X, Y](Ap(A, B)
(implicit aIsFXY: A#typeOf =:= (X⊃Y), bIsX: B#typeOf =:= X) : TypeOf =
{ type typeOf = Y }
这就是我卡住的地方。我需要表示 S 和 K 组合子的类型。但是,它们是普遍量化的类型。在您开始应用它们之前,您不知道它们的实际类型。我们以 K 为例。
(K x:X y:Y) : X
(K x:X) : ∀Y.Y => X
(K) : ∀X.x => ∀Y.Y => X
前几次我尝试使用它,我将 K 参数化为 K[X, Y],但这(灾难性地)多态性不足。K 的类型应该等待第一个参数的类型,然后是下一个参数的类型。如果您只将 K 应用于一个值,则下一个参数的类型不应该是固定的。您应该能够获取 (K x:X) 并将其应用于字符串、int 或任何您喜欢的类型。
所以我的问题是如何编写为 S 和 K 生成 typeOf 的隐式,以及如何正确处理∀量化类型。也许我想要这样的东西?
implicit def typeOfK(k: K.type): TypeOf = { type typeOf = ∀[X, X ⊃ (∀[Y, Y⊃X])] }
但是,我不确定我应该如何编写 ∀ 类型来完成管道。我有一种感觉,除了让 ∀ 正确之外,除了现有的 A#typeOf =:= ⊃[ ...] 一。
谢谢,
马修