为什么从 GHCi 中的 monad 出来的函数类型会发生变化 [英] Why does the type of a function change when it comes out of a monad in GHCi

查看:21
本文介绍了为什么从 GHCi 中的 monad 出来的函数类型会发生变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从 monad 出来的函数的类型发生了一些变化.

Something changes about the type of a function when it comes out of a monad.

在 GHCI 中:

> :t map
map :: (a -> b) -> [a] -> [b]
> a <- return map
> :t a
a :: (GHC.Prim.Any -> GHC.Prim.Any)
 -> [GHC.Prim.Any] -> [GHC.Prim.Any]

此更改使函数难以存储在更高级别的类型中.

This change makes it hard to store the function in a higher rank type.

这里发生了什么,我可以让它不发生吗?

What is happening here and can I make it not happen?

(这是否也违反了单子定律之一?)

(Also doesn't this violate one of the monad laws?)

推荐答案

首先,像 a <- return map 这样的事情没有意义——它和 一样let a = map,效果很好.也就是说,我认为这不是你的问题......

First of all, there is no point in doing anything like a <- return map - its the same as let a = map, which works just fine. That said, I don't think that is your question...

查看 GHC.Prim 的文档.Any 为我们提供了关于 Any 角色的重要提示.

Checking out the documentation of GHC.Prim.Any which gives us a big hint as to the role of Any.

它也用于在类型之后实例化不受约束的类型变量检查.例如,length 有类型

It's also used to instantiate un-constrained type variables after type checking. For example, length has type

length :: forall a. [a] -> Int 

并且空列表的列表数据具有类型

and the list datacon for the empty list has type

[] :: forall a. [a]

为了将这两个术语组合为 length [] a类型应用程序是必需的,但没有限制选择.在这种情况下,GHC 使用 Any

In order to compose these two terms as length [] a type application is required, but there is no constraint on the choice. In this situation GHC uses Any

(就类型应用程序语法而言,类似于 length @Any ([] @Any *))

(In terms of type application syntax, that looks like length @Any ([] @Any *))

问题在于,当 GHCi 看到 x <- return map 时,它会尝试将其脱糖为 return map >>= x ->...... 部分是您接下来输入 GHCi 的任何内容.通常它会根据 ... 计算出 map 的类型变量将被实例化为什么(或者它们是否应该被实例化为任何东西),但是因为它什么都没有.

The problem is that when GHCi sees x <- return map it tries to desugar it to return map >>= x -> ... but the ... part is whatever you enter next into GHCi. Normally it would figure out what the type variables of map are going to be instantiated to (or whether they even should be instantiated to anything) based the ..., but since it has nothing there.

@sepp2k 指出的另一个关键点是 x 不能被赋予多态类型 因为 (>>=) 期望(在其 RHS 上)一个 rank-1 函数,这意味着它的参数不能是多态的.(放松这个条件会让你直接进入 RankNTypes,此时你将失去可靠推断类型的能力.)

Another key point that @sepp2k points out is that x can't be given a polymorphic type because (>>=) expects (on its RHS) a rank-1 function, and that means its argument can't be polymorphic. (Loosening this condition pushes you straight into RankNTypes at which point you lose the ability to infer types reliably.)

因此,需要 x 是单态的并且没有信息来帮助它实例化阻止 x 单态的类型变量,它默认使用 Any.这意味着不是 (a -> b) ->;[一]->[b] 你得到 (Any -> Any) ->[任何]->[任何].

Therefore, needing x to be monomorphic and having no information to help it instantiate the type variables that prevent x from being monomorphic, it defaults to using Any. That means that instead of (a -> b) -> [a] -> [b] you get (Any -> Any) -> [Any] -> [Any].

这篇关于为什么从 GHCi 中的 monad 出来的函数类型会发生变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆