Haskell 在使用序列运算符后无法推断 monad 的返回类型

问题描述 投票:0回答:1

以下代码

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 无法推断出这一点?

haskell monads
1个回答
0
投票

问题本质上是

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
© www.soinside.com 2019 - 2024. All rights reserved.