为什么函数的类型在GHCi中出现monad时会发生变化

Joh*_*ler 2 polymorphism haskell ghc ghci

当一个函数出现在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]
Run Code Online (Sandbox Code Playgroud)

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

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

(这也不违反monad法律之一吗?)

Ale*_*lec 6

首先,做任何事都没有意义a <- return map- 它一样let a = map,工作得很好.那就是说,我认为这不是你的问题......


查看文档GHC.Prim.Any,给我们一个关于角色的重要提示Any.

它还用于在类型检查后实例化非约束类型变量.例如,length有类型

length :: forall a. [a] -> Int 
Run Code Online (Sandbox Code Playgroud)

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

[] :: forall a. [a]
Run Code Online (Sandbox Code Playgroud)

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

(在类型应用程序语法方面,看起来像length @Any ([] @Any *))

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

@ sepp2k指出的另一个关键点是x 不能给出多态类型,因为(>>=)期望(在其RHS上)是一个rank-1函数,这意味着它的参数不能是多态的.(放松这个条件会直接RankNTypes导致你无法可靠地推断出类型.)

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