我正试图通过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
是函数(λ(a : *) → λ(x : a) → x)
,类型为idType == (∀(t : *) → t → t)
。为什么我收到这个错误?
答案 0 :(得分:4)
您
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
是错误类型的(分支的不同类型),但是你可能会得到粗略的想法。为了更精确地编写它,我需要类似于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
值。
答案 1 :(得分:3)
这里的问题是教堂式的打字(这里是一个很好的blogpost和一些discussion),一切都必须从一开始就是好的打字:如果你的打字很好{{ 1}}和类型良好的f
,然后您可以将x
应用于f
(如果类型匹配)。如果x
的输入不是很好,那么它就不是一个合法的术语,即使可以为f
分配类型,也会出现错误。
您的f x
输入不是很好:λ (idType : *) → λ (id : idType) → (id idType)
是id
类型的术语,它不是接收idType
的函数,因此您无法应用它到*
。