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