什么是使用'绑定'来进行类型检查依赖lambda抽象的正确方法?

时间:2015-05-25 08:46:19

标签: haskell lambda-calculus dependent-type

我正在实现一种简单的依赖类型语言,类似于described by Lennart Augustsson,同时也使用bound来管理绑定。

当检查一个相关的lambda术语时,例如λt:* . λx:t . x,我需要:

  1. "输入"外部lambda绑定器,通过将t实例化为某事
  2. Typecheck λx:t . x,屈服于∀x:t . t
  3. Pi-abstract t,屈服于∀t:* . ∀x:t . t
  4. 如果lambda是非依赖的,我可以在步骤1中使用 type 实例化t,因为类型是我需要知道的关于变量的类型第2步。 但是在第3步,我缺乏决定抽象的变量的信息。

    我可以引入新的名称供应并使用包含类型和唯一名称的t来实例化Bound.Name.Name。但我认为bound我不需要生成新的名字。

    我是否有其他解决方案?

1 个答案:

答案 0 :(得分:8)

我们需要某种上下文来跟踪lambda参数。但是,我们不一定需要实例化它们,因为bound给出了de Bruijn索引,我们可以使用这些索引来索引上下文。

实际上,使用索引有点涉及,因为类型级机制通过{{1}的嵌套反映当前范围的大小(或者换句话说,表达式中的当前深度) } -s。它需要使用多态递归或GADT。它还阻止我们将状态存储在状态monad中(因为大小因此上下文的类型随着我们的递归而改变)。我想知道我们是否可以使用索引状态monad;这将是一个有趣的实验。但我离题了。

最简单的解决方案是将上下文表示为函数:

Var

type TC a = Either String a -- our checker monad type Cxt a = a -> TC (Type a) -- the context 输入本质上是de Bruijn索引,我们通过将函数应用于索引来查找类型。我们可以通过以下方式定义空上下文:

a

我们可以扩展上下文:

emptyCxt :: Cxt a
emptyCxt = const $ Left "variable not in scope"

上下文的大小在consCxt :: Type a -> Cxt a -> Cxt (Var () a) consCxt ty cxt (B ()) = pure (F <$> ty) consCxt ty cxt (F a) = (F <$>) <$> cxt a 嵌套中编码。在返回类型中,尺寸的增加是显而易见的。

现在我们可以编写类型检查器了。这里的要点是我们使用VarfromScope来获取绑定器,并且我们带有适当扩展的toScope(其类型排列完全正确)。

Cxt

以上是the working code containing上述定义。我希望我没有把它弄得太糟糕。