繁体   English   中英

这些明确的“forall”在做什么?

[英]What are these explicit “forall”s doing?

这段代码中forall的目的是什么?

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

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


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

此外,它可能并不重要,但GHCi允许我在给出>> a类型时省略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

(没有错误)。

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

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

类型变量也是如此, forall是绑定类型变量的一种方式。 任何地方,你看到没有明确的约束(例如,一个类型变量class Foo a where ...结合a ,它隐含一个绑定的类定义中) forall

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM