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法律之一吗?)
首先,做任何事都没有意义a <- return map
- 它一样let a = map
,工作得很好.那就是说,我认为这不是你的问题......
查看文档GHC.Prim.Any
,给我们一个关于角色的重要提示Any
.
它还用于在类型检查后实例化非约束类型变量.例如,
length
有类型Run Code Online (Sandbox Code Playgroud)length :: forall a. [a] -> Int
并且空列表的列表数据具有类型
Run Code Online (Sandbox Code Playgroud)[] :: forall a. [a]
为了将这两个术语组成
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]
.