Haskell 什么是明确的;forall“;他在干什么?

Haskell 什么是明确的;forall“;他在干什么?,haskell,higher-rank-types,forall,Haskell,Higher Rank Types,Forall,此代码中所有s的用途是什么 class Monad m where (>>=) :: forall a b. m a -> (a -> m b) -> m b (>>) :: forall a b. m a -> m b -> m b -- Explicit for-alls so that we know what order to -- give type ar

此代码中所有s的
用途是什么

class  Monad m  where
    (>>=)       :: forall a b. m a -> (a -> m b) -> m b
    (>>)        :: forall a b. m a -> m b -> m b
        -- Explicit for-alls so that we know what order to
        -- give type arguments when desugaring
(省略了一些代码)。这是源于的代码


我的背景:我真的不明白所有的
,也不明白Haskell什么时候暗含了这些

此外,这可能并不重要,但GHCi允许我在给出
>
类型时忽略所有

Prelude> :t (>>) :: Monad m => m a -> m b -> m b
(>>) :: Monad m => m a -> m b -> m b
  :: (Monad m) => m a -> m b -> m b
(没有错误)

我的背景:我真的不明白哈斯凯尔什么时候含蓄地说了这些话

<> >,考虑<代码> ID <代码>的类型,<代码> A> > A<代码>。
a
是什么意思,它来自哪里?定义值时,不能只使用未在任何地方定义的任意变量。您需要顶级定义、函数参数或
where
子句&c。一般来说,如果你使用一个变量,在某个地方

类型变量也是如此,
forall
是绑定类型变量的一种方法。无论您在何处看到未显式绑定的类型变量(例如,
class Foo a where…
在类定义中绑定
a
),它都隐式地由
for all
绑定

因此,
id
的类型对于所有a都是隐式的
。a->a
。这是什么意思?跟上面说的差不多。我们可以为所有可能的类型
a
获取一个类型
a->a
,或者从另一个角度来看,如果您选择任何特定类型,您可以获取一个表示“从所选类型到自身的函数”的类型。后一个短语听起来有点像定义函数,因此您可以将
forall
看作类似于类型的lambda抽象

GHC在编译过程中使用各种中间表示,它应用的转换之一是使与函数的相似性更直接:隐式
forall
s被显式化,并且任何多态值用于特定类型的地方,它首先应用于类型参数

我们甚至可以将所有
s和lambdas作为一个表达式编写。我将暂时滥用符号,并将所有a.
替换为
/\a=>
,以实现视觉一致性。在这种风格中,我们可以定义
id=/\a=>\(x::a)->(x::a)
或类似的东西。因此,代码中类似于
id-True
的表达式最终会转换为类似于
id-Bool-True
的表达式;仅仅是
id True
就不再有意义了

正如您可以对函数参数进行重新排序一样,您也可以对类型参数进行重新排序,只需遵守(非常明显的)限制,即类型参数必须位于该类型的任何值参数之前。由于隐式
forall
s始终是最外层,因此GHC在将它们显式化时可能会选择它想要的任何顺序。在正常情况下,这显然无关紧要


我不确定在这种情况下到底发生了什么,但根据这些评论,我猜转换为使用显式类型参数和取消
do
符号在某种意义上是互不知道的,因此显式指定类型参数的顺序以确保一致性。毕竟,如果有什么东西盲目地将两个类型参数应用于一个表达式,那么该表达式的类型是否为所有AB的
,就非常重要了。m a->m b->m b
或所有b a的
。m a->m b->m b

@sacundim的可能副本不一致;问题不在于
forall
通常做什么,也不在于更高级别的类型是什么。问题是,具体地说,
forall
在这段代码中做了什么,根据它后面的注释。这是一个明确的forall示例。它们不是等级更高的类型,移除孔不会改变类型。我不太清楚为什么他们在这里占优势。该注释表明,它有助于编译器在去糖化阶段进行编译。是的,这些正是语言隐式指定的孔,所以从语义上讲,它们的存在或不存在不会改变任何东西。然而,我不知道编译器如何利用它们在去糖化阶段的存在。