Scala 组合器微积分数据模型的类型推断
我正在 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 =:= ⊃[ 之外,还将有第二个隐含的 typeOfAp 来处理 A#typeOf =:= ∀[...] 情况...] 一。
谢谢,
马修
I'm trying out a very light-weight encoding of combinator calculus in scala. Initially, I'm simply implementing the S and K combinators, application and constant values. Later I hope to lift scala functions in and allow evaluation of an expression as a scala function. However, that's for later. Here is what I have so far.
/** 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
Now I would like to do some type inference over this. For simplicity of implementing small- and large-step reduction, the data model is untyped, so I'd like types to be external to this structure. Let's introduce something to hold the type information.
trait TypeOf { type typeOf }
The Value type is easy.
implicit def typeOfValue[T](vt: Value[T]) : TypeOf =
new TypeOf { type typeOf = T }
Application is a little more tricky, but basically boils down to function application. Let's introduce a type ⊃ for combinator application, to avoid confusion with normal scala application.
/** 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 }
This is where I get stuck. I need to represent the type of the S and K combinators. However, they are universally quantified types. You don't know their actual type until you start applying them. Let's take K as an example.
(K x:X y:Y) : X
(K x:X) : ∀Y.Y => X
(K) : ∀X.x => ∀Y.Y => X
The first couple of times I tried to work with this, I make K parameterised as K[X, Y], but this is (catastrophically) insufficiently polymorphic. The type of K should be waiting for the type of the first argument, and then of the next. If you apply K to just one value, then the type of the next argument should not yet be fixed. You should be able to take (K x:X) and apply it to a string, or to an int or whatever type you like.
So my problem is how to write the implicit that generates the typeOf for S and K, and how to handle the ∀-quantified types correctly. Perhaps I want something like this?
implicit def typeOfK(k: K.type): TypeOf = { type typeOf = ∀[X, X ⊃ (∀[Y, Y⊃X])] }
However, I'm not sure how I should be writing the ∀ type to do the plumbing. I've a feeling that in addition to getting ∀ right, there will be a second implicit for typeOfAp to handle the A#typeOf =:= ∀[...] case in addition to the exiting A#typeOf =:= ⊃[...] one.
Thanks,
Matthew
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这有帮助吗?
Does this help?