Haskell 我们说T1比T2更多态是什么意思?
我正在用论文学习类型推理,我一开始就陷入了困境。我基本上对多态性大于关系的概念感到困惑,因此无法继续下去 在第3.3节中,它指出: 如果函数的类型比函数的参数类型更具多态性,则函数可以接受参数 在我的理解中,说Haskell 我们说T1比T2更多态是什么意思?,haskell,type-inference,higher-rank-types,Haskell,Type Inference,Higher Rank Types,我正在用论文学习类型推理,我一开始就陷入了困境。我基本上对多态性大于关系的概念感到困惑,因此无法继续下去 在第3.3节中,它指出: 如果函数的类型比函数的参数类型更具多态性,则函数可以接受参数 在我的理解中,说T1比T2更多态,就是说任何类型为T2的实例都必须满足类型T1。根据我的定义,forall a。a比Int更具多态性全部a b。a->b->b比所有a的更具多态性。a->a->a 据我所知,存在冲突。鉴于: f :: (forall a. a) -> Int k :: (forall
T1
比T2
更多态,就是说任何类型为T2
的实例都必须满足类型T1
。根据我的定义,forall a。a
比Int更具多态性<代码>全部a b。a->b->b比所有a的更具多态性。a->a->a
据我所知,存在冲突。鉴于:
f :: (forall a. a) -> Int
k :: (forall a. a -> a)
(f k)
显然是有效的[1]。然后根据这篇文章的引文,forall a。对于所有a,a->a
应该比更具多态性。a
。然而,举个例子,文本1
将满足所有a的。a
,但显然它不是所有a的。a->a
,因此根据我的定义,适用于所有a。对于所有a而言,
应该比更具多态性。a->a
。这与文章中关于多态性大于关系的描述相矛盾
我正在寻找一个关于这种关系到底是什么的清晰解释。谢谢
更新:
[1] :正如在评论d8d0d65b3f7cf42中,我注意到(对于所有a.a)
与(对于所有a.a->a)
不兼容。我的理解应该有问题。我注意到(forall a.a->Int)
可以接受类型为(forall a.a->a)
的参数,而(forall a.a)->Int不能。我不知道这个案子为什么会这样
尽管我有错误的理解,我仍然期待着一个好的解释,解释什么是比关系更多态的。谢谢:)正如在对OP的评论中指出的,(未定义::(对于所有a.a)->Int)(未定义::(对于所有a.a->a))
不会进行打字检查,事实上,对于所有a。a->a
对于所有a来说都不比更具多态性。a
,因此这里没有矛盾
另一方面,(未定义::(forall a.a->Int))(未定义::(forall a.a->a))
类型检查,所以对于all a。a->a
必须将a
包含在函数类型中,对吗?这似乎违反直觉,但事实恰恰如此。让我解释一下
包容与类型变量
包容(或者说:多态子类型)意味着“至少是多态的”,因此它更类似于a
(或者可能是不同的约束,取决于我们对类型推理系统的选择。实际步骤可能与我在下面的示例中所描述的有很大不同)
一个简单的分步示例:
-- goal
(forall a. a -> Int) <= (Int -> Int)
-- instantiate variable on the left hand side with a fresh type variable.
(tvar a' -> Int) <= (Int -> Int)
-- check return type subsumption
Int <= Int -- OK
-- check argument type subsumption
Int <= tvar a' -- OK, add "tvar b = Int" to the set of constraints.
-- Done.
基本上,我们只能用skolem变量做两件事:
我们可以自由地总结skolem a a)->Int)Int)->Int)
--请记住:上下文可以提供“forall a.a->Int”-s并要求“Int”-s。
--检查退货类型
Int)a)
--在左边实例化
(tvar a'->Int)a)
--在右边实例化
(tvar a'->Int)skolem a')
--检查退货类型
Int b)“显然有效”-您试过了吗?在ghci中::set-XRankNTypes
然后(未定义::(对于所有a.a)->Int)(未定义::(对于所有a.a->a))
@d8d0d65b3f7cf42哦,它是无效的。但是(未定义::(forall a.a->Int))(未定义::(forall a.a->a))
是有效的。我相信更多多态性大致意味着如果T
比U
更多态,如果x::T
和y::U
,如果我们可以专门化y::A
,那么我们就可以专门化x::A
我看不出OP的问题。引用文件的第3.3节是“包容”,包含示例,以及对奥德斯基/劳弗的引用,文件附录中的代码实现了“包容检查”。在更正的OP示例中,a
被包含在所有a中。a->a
因为在该上下文中,a
是一个非刚性类型变量-为什么在该上下文中不需要SKOLemission(未定义::(对于所有a.a->Int))(未定义::(对于所有a.a->a))
就像你的另一个例子一样,即(对于所有a.a->Int)Int)
,其中b
是被忽略的。@scriptum那里要显示的子类型关系是(对于所有a.a->a)。这个答案对我来说是一个启发,对理解这个主题有很大帮助。因此,我想分享我新学到的知识,以便其他人也能从中受益:
-- goal
(forall a. a -> Int) <= (forall b. b -> Int)
-- instantiate variable on the left
(tvar a' -> Int) <= (forall b. b -> Int)
-- instantiate variable on the right
(tvar a' -> Int) <= (skolem b' -> Int)
-- check return types
Int <= Int -- OK
-- check argument types
skolem b' <= tvar a' -- OK, record the "tvar a' = skolem b'" constraint
-- Done.
-- goal
((forall a. a -> a) -> Int) <= ((forall a. a -> Int) -> Int)
-- remember: the context can supply "forall a. a -> Int"-s and demands "Int"-s.
-- check return types
Int <= Int -- OK
-- check argument types
(forall a. a -> Int) <= (forall a. a -> a)
-- instantiate on the left
(tvar a' -> Int) <= (forall a. a -> a)
-- instantiate on the right
(tvar a' -> Int) <= (skolem a'' -> skolem a'')
-- check return types
Int <= skolem a'' -- FAIL: this clearly does not hold.
-- Abort.