haskell - 这些显式的 "forall"在做什么?

标签 haskell higher-rank-types forall

此代码中 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 允许我在给 >> 类型时省略 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

(没有错误)。

最佳答案

My background: I don't really understand forall or when Haskell has them implicitly.

好的,考虑 id 的类型, a -> aa 是什么意思?意思是,它从哪里来?定义值时,不能只使用未在任何地方定义的任意变量。您需要一个顶级定义,或函数参数,或 where条款,等等。一般来说,如果使用变量,it must be bound某处。

类型变量也是如此,forall是绑定(bind)类型变量的一种方式。在任何地方,您看到未显式绑定(bind)的类型变量(例如,class Foo a where ... 在类定义中绑定(bind) a),它由 forall 隐式绑定(bind)。 。

所以,id 的类型隐含地 forall a. a -> a 。这是什么意思?和它说的差不多。我们可以得到一个类型a -> a 对于所有可能的类型 a ,或者从另一个角度来看,如果您选择任何特定类型,您可以获得一个表示“从您选择的类型到其自身的函数”的类型。后一种措辞听起来有点像定义函数,因此您可以想到 forall类似于类型的 lambda 抽象。

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

我们甚至可以同时写 forall s 和 lambda 作为一个表达式。我将暂时滥用符号并替换 forall a./\a =>为了视觉一致性。在这种风格中,我们可以定义 id = /\a => \(x::a) -> (x::a)或类似的东西。因此,像 id True 这样的表达式你的代码最终会被翻译成类似 id Bool True 的内容反而;只是id True甚至不再有意义。

正如您可以对函数参数重新排序一样,您也可以对类型参数重新排序,仅受(相当明显的)限制,即类型参数必须位于该类型的任何值参数之前。由于隐式forall s 始终是最外层,GHC 在使它们显式时可以选择它想要的任何顺序。在正常情况下,这显然并不重要。

我不确定这种情况下到底发生了什么,但根据评论,我猜测转换为使用显式类型参数以及 do 的脱糖。从某种意义上说,表示法彼此不知道,因此显式指定类型参数的顺序以确保一致性。毕竟,如果盲目地将两个类型参数应用于表达式,那么该表达式的类型是否为 forall a b. m a -> m b -> m b 就非常重要。或forall b a. m a -> m b -> m b !

关于haskell - 这些显式的 "forall"在做什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12519878/

相关文章:

haskell - 将两个(或多个)选项值应用于 F# 中的函数的正确方法

linux - 在 GHC 编译的二进制文件中使用过多的神秘系统时间

Haskell Gloss,在动画功能中从控制台读取不会更新绘图

haskell - 具有 RankNTypes 的新类型

haskell - 类型同义词究竟是如何工作的?

haskell - 使基本 Haskell 类型成为新类型类的实例

haskell - 类型别名混淆的 RankNTypes

haskell - 如果没有明确提及,如何知道模块是否需要 RankNTypes 还是 ExistentialTypes?

haskell - GHC 9 中的 `forall {..}`

.net - PLINQ 更新失败