Haskell 什么是明确的;forall“;他在干什么?
此代码中所有s的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
用途是什么
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示例。它们不是等级更高的类型,移除孔不会改变类型。我不太清楚为什么他们在这里占优势。该注释表明,它有助于编译器在去糖化阶段进行编译。是的,这些正是语言隐式指定的孔,所以从语义上讲,它们的存在或不存在不会改变任何东西。然而,我不知道编译器如何利用它们在去糖化阶段的存在。