Haskell 我们说T1比T2更多态是什么意思?

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

我正在用论文学习类型推理,我一开始就陷入了困境。我基本上对多态性大于关系的概念感到困惑,因此无法继续下去

在第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 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.