这些明确的"forall"在做什么?

Mat*_*ick 17 haskell forall 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 arguments when desugaring
Run Code Online (Sandbox Code Playgroud)

(省略了一些代码).这来自Monads的代码.


我的背景:我不太懂,forall或者Haskell隐含地拥有它们.

此外,它可能并不重要,但GHCi允许我forall在给出>>类型时省略:

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
Run Code Online (Sandbox Code Playgroud)

(没有错误).

C. *_*ann 11

我的背景:我真的不了解forall或Haskell隐含地拥有它们.

好吧,考虑的类型id,a -> a.什么a意思,它来自哪里?定义值时,不能只使用未在任何位置定义的任意变量.您需要顶级定义,函数参数或where子句,&c.通常,如果使用变量,则必须将其绑定到某处.

类型变量也是如此,并且forall是一种绑定类型变量的方法.在任何地方,您都会看到未明确绑定的类型变量(例如,在类定义中class Foo a where ...绑定a),它由a隐式绑定forall.

所以,id隐含的类型forall a. a -> a.这是什么意思?几乎就是这么说的.我们可以获得a -> a 所有可能类型的类型a,或者从另一个角度获取,如果您选择任何特定类型,您可以获得表示"从您选择的类型到自身的函数"的类型.后面的措辞听起来有点像定义一个函数,因此你可以认为forall它类似于lambda抽象类型.

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

我们甚至可以将foralls和lambdas都写成一个表达式.我会滥用标记了一下,替换forall a./\a =>视觉的一致性.在这种风格中,我们可以定义id = /\a => \(x::a) -> (x::a)或类似的东西.因此,id True代码中的表达式最终会转换为类似的内容id Bool True; 只是id True不再有意义.

正如您可以重新排序函数参数一样,您也可以重新排序类型参数,仅受限于类型参数必须在该类型的任何值参数之前出现的(相当明显的)限制.由于隐式foralls始终是最外层,因此GHC可能会在明确时选择任何所需的顺序.一般情况下,这显然无所谓.

我不确定在这种情况下到底发生了什么,但根据评论我会猜测do,在某种意义上,转换为使用显式类型参数和符号的消除是彼此不了解的,因此顺序明确指定类型参数以确保一致性.毕竟,如果某些东西盲目地将两个类型的参数应用于表达式,那么该表达式的类型是否为forall a b. m a -> m b -> m b或者很重要forall b a. m a -> m b -> m b!