以下代码
import Control.Monad.Writer
class Foo c where
fromInt :: Int -> c
instance Foo [Int] where
fromInt n = [n]
instance (Monoid c, Foo c) => Foo (Writer c ()) where
fromInt d = writer ((),fromInt d)
onetwo :: Writer [Int] ()
onetwo = fromInt 1 >> fromInt 2
产生以下错误:
Ambiguous type variable `a0' arising from a use of `fromInt' prevents the constraint
`(Foo (WriterT [Int] Data.Functor.Identity.Identity a0))'
from being solved.
所以看起来Haskell无法推断出Writer monad的返回类型,但我不明白为什么,因为它只能是基于
fromInt
实现的单元类型。
为什么 Haskell 无法推断出这一点?
问题本质上是
fromInt 1 >> fromInt 2
中的左操作数。事实上,(>>)
具有类型 (>>) :: Monad m => m a -> m b -> m b
。这意味着根据结果的类型,我们知道 m
和 b
是什么,但不知道 a
。
这是一个问题。是的,我们定义了一个实例
instance Foo (Writer c ())
,目前这是唯一的实例。但这并不排除(另一个)程序员稍后可以添加一个实例:
instance Foo (Writer [Int] Bool)
-- …
例如,由于
a
未知,因此它可以是任何东西。
我们可以通过指定第一个操作数的类型来解决这个问题,例如:
onetwo :: Writer [Int] ()
onetwo = (fromInt 1 :: Writer [Int] ()) >> fromInt 2