Haskell 无法推断(m~m1)
在GHC中编译此程序时:Haskell 无法推断(m~m1),haskell,Haskell,在GHC中编译此程序时: import Control.Monad f x = let g y = let h z = liftM not x in h 0 in g 0 我收到一个错误: test.hs:5:21: Could not deduce (m ~ m1) from the context (Monad m) bound by the inferred type of f :: Monad m => m Bool ->
import Control.Monad
f x = let
g y = let
h z = liftM not x
in h 0
in g 0
我收到一个错误:
test.hs:5:21:
Could not deduce (m ~ m1)
from the context (Monad m)
bound by the inferred type of f :: Monad m => m Bool -> m Bool
at test.hs:(3,1)-(7,8)
or from (m Bool ~ m1 Bool, Monad m1)
bound by the inferred type of
h :: (m Bool ~ m1 Bool, Monad m1) => t1 -> m1 Bool
at test.hs:5:5-21
`m' is a rigid type variable bound by
the inferred type of f :: Monad m => m Bool -> m Bool
at test.hs:3:1
`m1' is a rigid type variable bound by
the inferred type of
h :: (m Bool ~ m1 Bool, Monad m1) => t1 -> m1 Bool
at test.hs:5:5
Expected type: m1 Bool
Actual type: m Bool
In the second argument of `liftM', namely `x'
In the expression: liftM not x
In an equation for `h': h z = liftM not x
为什么??另外,为
f
(f::Monad m=>m Bool->m Bool
)提供显式类型签名会使错误消失。但根据错误消息,这与Haskell为f
自动推断的类型完全相同 事实上,这很简单。let
绑定变量的推断类型隐式地泛化为类型模式,因此在您的方式中有一个量词。h
的一般类型为:
h :: forall a m. (Monad m) => a -> m Bool
f :: forall m. (Monad m) => m Bool -> m Bool
而f
的一般类型为:
h :: forall a m. (Monad m) => a -> m Bool
f :: forall m. (Monad m) => m Bool -> m Bool
它们不是相同的m
。如果您编写以下内容,您将得到基本相同的错误:
f :: (Monad m) => m Bool -> m Bool
f x = let
g y = let
h :: (Monad m) => a -> m Bool
h z = liftM not x
in h 0
in g 0
您可以通过启用“作用域类型变量”扩展来修复它:
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall m. (Monad m) => m Bool -> m Bool
f x = let
g y = let
h :: a -> m Bool
h z = liftM not x
in h 0
in g 0
或者通过禁用带有“单态局部绑定”扩展的
let
-泛化,monocalbinds
单态限制?单态限制仅适用于简单模式绑定,这里没有。无论如何,添加-xnomonomomorphismrestriction
没有任何效果。我认为这与let泛化有关,因为错误会随着-xmonocalbinds
消失,这并不是那么简单,因为对于ghc,为什么fx=let gy=liftM而不是g0中的x发生这种情况?g
的类型也应该用同样的方法来概括。也许这是一个bug。在这种情况下,问题和答案是一个很好的例子和开始寻找的地方。