为什么这个简单的 Morte 程序不能进行类型检查?

Why won't this simple Morte program typecheck?

我正在尝试通过 Morte 更好地理解构造微积分。我的第一次尝试是调用身份函数本身。然而,

(
λ (idType : *) →
λ (id : idType) → 
(id idType))

(∀(t : *) → ∀(x : t) → t)
(λ(a : *) → λ(x : a) → x)

该程序编译失败并出现错误:

Context:
idType : *
id : idType

Expression: id idType

Error: Only functions may be applied to values

这对我来说没有意义,因为 id 是类型 idType == (∀(t : *) → t → t) 的函数 (λ(a : *) → λ(x : a) → x)。为什么我会收到此错误消息?

你的

T = (λ (idType : *) →
     λ (id : idType) → 
    (id idType))

打错字了。否则 T nat 4 也会输入检查(假装我们有自然数来帮助直觉)。


如果你想写一个应用程序函数(像Haskell的$)你可以使用

apply = 
    (λ (a b : *) →
     λ (f : a -> b) → 
     λ (x : a) → 
     f x)

请注意,以上仅适用于非依赖性 f。在从属情况下,b 可以依赖于类型 a 的实际值,使事情变得更加复杂,因为现在 b 是一个函数。

applyDep = 
    (λ (a : *) →
     λ (b : a -> *) →
     λ (f : ∀(x : a) -> b x) → 
     λ (x : a) → 
     f x)

示例(简化语法):

applyDep 
  Bool
  (λ (x : Bool) -> if x then Int else Char)
  (λ (x : Bool) -> if x then 4 else 'd')
  True

上面我对依赖函数(最后一个 lambda)相当草率,因为 if 类型不正确(分支的类型不同),但你可能会得到粗略的想法。为了更准确地写出来,我需要像依赖 match/case Coq 那样的东西(或者依赖于 Bool 的依赖消除器):

fun x: Bool =>
  match x as y return (if y then Int else Char) with
  | True  => 3
  | False => 'a'
  end

在上面的"if"中,我要说清楚两个分支的类型是不同的(Int vs Char),但是如果我们可以输入将其作为 g x 的结果,其中 g = fun y => if y then Int else Char。基本上,结果类型现在取决于 x 值。

这里的问题是,使用教堂风格的打字(这里是一个很好的 blogpost and some discussion)所有内容都必须从一开始就打好:如果你有一个打好字的 f 和一个类型正确的 x,那么您可以将 f 应用到 x(如果类型匹配)。如果 f 的类型不正确,那么它就不是一个合法的术语并且你有一个错误,即使可以为 f x 分配一个类型。

你的 λ (idType : *) → λ (id : idType) → (id idType) 类型不正确:id 是类型 idType 的术语,它不是接收 * 的函数,所以你不能将其应用于 idType.