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

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

问题描述



在GHCI中:



pre> > :t map
map ::(a - > b) - > [a] - > [b]
> a< - 退货地图
> :t a
a ::(GHC.Prim.Any - > GHC.Prim.Any)
- > [GHC.Prim.Any] - > [GHC.Prim.Any]

这种改变使得很难将函数存储在更高等级的类型中。



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



(这也违反了单子法之一吗?)

解决方案 a< - return map - 它与 let a = map ,它工作得很好。这就是说,我不认为这是你的问题...






检查 GHC.Prim.Any ,这给了我们一个关于任何角色的大提示。


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

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

和空列表的datacon列表中有类型

  [] :: forall a。 [a] 

为了将这两个术语合并为 length []
类型的应用程序是必需的,但对
选项没有限制。在这种情况下,GHC使用任何




(就类型应用程序语法而言,看起来像长度@Any([] @Any *)



问题是,当GHCi看到 x < - return map 它试图将它解析为 return map>> = \ x - > ... ,但 ... 部分是您接下来输入到GHCi中的任何部分。通常,它会根据来确定 map 的类型变量将被实例化为什么(或者它们是否应该被实例化为任何东西)。 .. ,但因为它没有任何内容。

@ sepp2k指出的另一个关键点是 x 不能被赋予多态类型因为(>> =)期望(在它的RHS上)一个1级函数,这意味着它的参数不能是多态的。 (松开这个条件会直接导致 RankNTypes 在这一点上你失去了可靠地推断类型的能力。)



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


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

In 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?)

解决方案

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...


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

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]

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

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

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.

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.)

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天全站免登陆