haskell如何确定隐式forall中类型变量的顺序?

JoL:

因此,我最近才了解并开始使用TypeApplications,并且想知道我们通常如何知道要分配的类型变量。我找到的文档中TypeApplications提到:

使用什么顺序来实例化类型变量?

类型变量从左到右的顺序出现在forall中。这是在类型变量级别进行实例化时发生的最合乎逻辑的顺序。嵌套的forall的工作方式略有不同,但是在具有多个变量的单个forall位置,发生了从左到右的顺序。(有关嵌套的forall,请参见下文)。

但是我还没有提到如何确定隐式forall中类型变量的顺序。我尝试查看不同的示例-fprint-explicit-foralls以查看是否存在简单的模式,但是在不同版本的ghci中我得到了不同的结果。:/

在ghci版本8.0.2中,我得到:

> :t (,,)
(,,) :: forall {c} {b} {a}. a -> b -> c -> (a, b, c)

在ghci版本8.4.3中,我得到:

> :t (,,)
(,,) :: forall {a} {b} {c}. a -> b -> c -> (a, b, c)

再说一遍,也许这仅仅是在8.0.2中打印allall的方式中的一个错误,因为否则类型应用程序似乎是使用forall的变量从右到左完成的,这与文档中所说的相反:

> :t (,,) @Bool
(,,) @Bool :: forall {c} {b}. Bool -> b -> c -> (Bool, b, c)

那么,将类型变量放入隐式forall中的顺序是否总是按照它们在类型主体中从左到右的顺序出现(包括约束)?

约阿希姆·布雷特纳(Joachim Breitner):

TL; DR:类型变量顺序由第一次从左到右的相遇确定。如有疑问,请使用:type +v

不要使用 :type

:type在这里使用会产生误导。:type推断整个表达式的类型。因此,当您编写时:t (,),类型检查器会查看

(,) :: forall a b. a -> b -> (a, b)

并使用新鲜的类型变量实例化所有的

(,) :: a1 -> b1 -> (a1, b1)

如果您要申请的话,这是必要的(,)las,您没有,所以类型推断几乎完成了,并且将所有自由变量都推广了,例如,

(,) :: forall {b} {a}. a -> b -> (a, b)

此步骤不能保证free变量的顺序,并且编译器可以自由更改。

还要注意,它写的forall {a}不是forall a,这意味着您不能在此处使用可见类型的应用程序。

:type +v

但是您当然可以使用(,) @Bool–但是这里的类型检查器对第一个表达式的处理不同,并且不执行此实例化/泛化步骤。

您也可以在GHCi中获得这种行为– 传递+v:type

:type +v (,)
(,) :: forall a b. a -> b -> (a, b)
:type +v (,) @Bool
(,) @Bool :: forall b. Bool -> b -> (Bool, b)

看,没有{…}类型变量!

这个命令来自哪里?

可见的应用程序类型的GHC用户指南部分规定:

如果标识符的类型签名不包括显式的forall,则类型变量参数以从左到右的顺序出现,其中变量在类型中出现。因此,foo :: Monad m => ab-> m(ac)将其类型变量按m,a,b,c进行排序。

这仅适用于具有显式类型签名的事物。推断类型中的变量没有确定的顺序,但是您也不能将推断类型中的表达式与一起使用VisibleTypeApplication

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章