了解Hindley的多型体
我正在阅读关于Hindley-Milner Type推理的维基百科文章,试图从中得出一些意见。 到目前为止,这是我所理解的:
int
或string
)或类型变量(如α
和β
)。 int
和string
)或类型构造函数(如Map
和Set
)。 α
和β
)表现为具体类型的占位符(如int
和string
)。 现在我在理解多类型时遇到了一些困难,但是在了解一下Haskell之后,我就这样做了:
int
和string
)和类型变量(如α
和β
)是*
类型的。 Map
和Set
)是类型的lambda抽象类型(例如Set
是kind * -> *
, Map
是kind * -> * -> *
)。 我不明白的是限定词是什么意思。 例如, ∀α.σ
代表什么? 我似乎无法做出正面或反面的结论,而我越读越接下去的段落就越感到困惑:
相反, polytype∀α.α - >α的函数可以将任何相同类型的值映射到自身,并且标识函数是此类型的值。 作为另一个例子∀α。(Setα) - > int是将所有有限集合映射到整数的函数的类型。 成员的数量是这种类型的值。 请注意,限定符只能出现在顶层,即例如类型∀α.α->∀α.α被类型语法排除,并且单型包含在多类型中,因此类型的一般形式为∀α1。 。 。 ∀αₙ.τ 。
首先,种类和多态类型是不同的东西。 你可以有一个HM类型的系统,其中所有类型都是相同类型的(*),你也可以有一个没有多态性但复杂类型的系统。
如果一个术语M
的类型是∀at
,就意味着对于任何类型s
我们可以替代s
为a
在t
(通常写为t[a:=s]
我们将具有M
的类型为t[a:=s]
。这有点类似于逻辑,我们可以用任何一个术语代替普遍量化的变量,但在这里我们正在处理类型。
这正是Haskell发生的情况,就是在Haskell中你看不到量词。 出现在一个类型签名的所有类型的变量都隐含量化,就像如果你有forall
在类型的前面。 例如, map
会有类型
map :: forall a . forall b . (a -> b) -> [a] -> [b]
如果没有这种隐式通用量化,类型变量a
和b
必须有一些固定的含义,并且map
不会是多态的。
HM算法区分类型(不含量词,单式)和类型模式(通用量化类型,多型)。 在某些地方使用类型模式(如let
)很重要,但在其他地方只允许使用类型。 这使得整个事情可以决定。
我也建议你阅读有关系统F.文章这是一个比较复杂的系统,它允许forall
的类型(因此那里的一切就被称为类型)的任何地方,但类型推断/检查是不可判定的。 它可以帮助您了解forall
的作品。 F系统在Girard,Lafont和Taylor的Proofs和Types中有深入的描述。
考虑Haskell中的l = x -> t
。 它是λ,它表示一个术语t
FITH变量x
,这将在后面被取代的(例如l 1
,不管它意味着)。 类似地, ∀α.σ
表示具有类型变量类型α
,即, f : ∀α.σ
如果一个函数由类型参数α
。 在某种意义上, σ
取决于α
,因此f
返回类型σ(α)
的值,其中α
将在后面的σ(α)
被替换,我们将得到一些具体类型。
在Haskell中,您可以省略∀
并像id : a -> a
一样定义函数。 允许省略量词的原因基本上是因为它们只允许顶级(没有RankNTypes
扩展名)。 你可以试试这段代码:
id2 : a -> a -- I named it id2 since id is already defined in Prelude
id2 x = x
如果你问ghci的id
( :t id
)的类型,它会返回a -> a
。 为了更精确(更多类型理论), id
的类型为∀a. a -> a
∀a. a -> a
。 现在,如果你添加到你的代码:
val = id2 3
,3具有的类型Int
,如此的类型Int
将被代入σ
,我们会得到一个具体类型Int -> Int
。
上一篇: Understanding Polytypes in Hindley
下一篇: What is Hindley