let a = b in c
可以被认为是(\a -> c) b
的语法糖,但在一般的打字环境中,情况并非如此。例如,在米尔纳微积分中let a = \x -> x in (a True, a 1)
是典型的,但看似等价的(\a -> (a True, a 1)) (\x -> x)
不是。
然而,后者在系统F中是典型的,第一个lambda的等级为2。
我的问题是:
是否让多态性成为在Milner演算的其他排名1世界中偷偷潜入的2级特征?
拥有单独的let
构造的目的似乎是指定哪些类型应该由类型检查器推广,哪些不是。它是否有任何其他用途?是否有任何理由扩展更强大的系统,例如系统F与单独的let
不是糖?有没有关于米尔纳微积分设计背后理由的论文,这对我来说不再是显而易见的?
系统F中\a -> (a True, a 1)
是否有最常规的类型?
在beta扩展下是否关闭了类型系统?即如果P是典型的且M N = P那么M是典型的吗?
一些澄清:
通过等价,我指的是等价模数类型注释。 “System F a la Church”是正确的术语吗?
我知道一般来说,主要的输入属性不能保存在F中,但是我的特定术语可能存在主体类型。
按let
我的意思是let
的非递归风格。使用递归let扩展系统F显然很有用,因为它允许非终止。
答案 0 :(得分:17)
W.r.t。问四个问题:
这件事的关键见解是,而不仅仅是输入一个 我们可以使用具有潜在多态参数类型的lambda抽象 正在输入一个(加糖的)抽象,它是(1)只应用一次 而且,这是(2)应用于静态已知的论证。 也就是说,我们可以首先对“论证”(即...的定义)进行处理 本地定义)键入重建来找到它 (多态)类型;然后将找到的类型分配给“参数” (定义);然后,最后,在扩展中键入正文 类型上下文。
请注意,这比一般的Rank-2类型要容易得多 推断。
请注意,严格来说,如果你要求定义带有一个类型注释,那么.. :: .. in ..只是系统F中的语法糖:let ..:.. = .. in。 ..
以下是系统F中的T in(\ a :: T - >(a True,a 1))的两个解决方案:forall b。 (forall a.a - > b) - > (b,b)和forall c d。 (forall a b.a - > b) - > (c,d)。请注意,它们中的任何一个都不比另一个更通用。通常,系统F不承认主要类型。
我认为这适用于简单输入的lambda演算?
答案 1 :(得分:4)
在任何可以表达“死代码”概念的微积分中,类型不会在beta扩展下保留。你可以弄清楚如何用任何可用的语言写出类似的内容:
if True then something typable else utter nonsense
例如,允许M = (\x y -> x) (something typable)
和N = (utter nonsense)
以及P = (something typable)
,以便M N = P
和P
可以打字,但M N
不是'吨。
...重读你的问题,我发现你只要求M
可以打字,但这似乎是一种非常奇怪的意义,可以让“保留在β扩展下”给我。无论如何,我不明白为什么像上面这样的论点不适用:只需让M
有一些不可分类的死代码。
答案 2 :(得分:3)
您可以键入(\a -> (a True, a 1)) (\x -> x)
如果不是只概括let表达式,而是概括所有 lambda抽象。完成此操作后,还需要在每个使用点实例化类型模式,而不仅仅是在实际使用引用它们的绑定器的位置。我不认为这实际上有任何问题,除了效率低得多。我记得在TAPL中对此进行了一些讨论,实际上也提出了类似的观点。
答案 3 :(得分:2)
另外,如果我没记错的话,完全正常的表单表达式有主要类型,它们不包含omega。
例如\ f x - >的主要类型f(f x)(教会数字2)将类似于((A - > B)/ \(B - > C)) - > A - > ç
答案 4 :(得分:0)
无法回答所有非常专业的问题,但不是,它不是第2级功能。在您编写时,只是让定义被量化,产生完全多态的rank-1类型,除非定义依赖于nouter范围内的某些单态值。
请注意,Haskell let
在其他语言中称为let rec
,允许定义相互递归的函数和值。这是你不想用lambda表达式和Y-combinator手动编码的东西。