5
instance Monad (Either a) where
     return = Left
     fail = Right
     Left x >>= f = f x
     Right x >>= _ = Right x

'baby.hs' 中的这段代码片段导致了可怕的编译错误:

Prelude> :l baby
[1 of 1] Compiling Main             ( baby.hs, interpreted )

baby.hs:2:18:
Couldn't match expected type `a1' against inferred type `a'
  `a1' is a rigid type variable bound by
       the type signature for `return' at <no location info>
  `a' is a rigid type variable bound by
      the instance declaration at baby.hs:1:23
In the expression: Left
In the definition of `return': return = Left
In the instance declaration for `Monad (Either a)'

baby.hs:3:16:
Couldn't match expected type `[Char]' against inferred type `a1'
  `a1' is a rigid type variable bound by
       the type signature for `fail' at <no location info>
  Expected type: String
  Inferred type: a1
In the expression: Right
In the definition of `fail': fail = Right

baby.hs:4:26:
Couldn't match expected type `a1' against inferred type `a'
  `a1' is a rigid type variable bound by
       the type signature for `>>=' at <no location info>
  `a' is a rigid type variable bound by
      the instance declaration at baby.hs:1:23
In the first argument of `f', namely `x'
In the expression: f x
In the definition of `>>=': Left x >>= f = f x

baby.hs:5:31:
Couldn't match expected type `b' against inferred type `a'
  `b' is a rigid type variable bound by
      the type signature for `>>=' at <no location info>
  `a' is a rigid type variable bound by
      the instance declaration at baby.hs:1:23
In the first argument of `Right', namely `x'
In the expression: Right x
In the definition of `>>=': Right x >>= _ = Right x
Failed, modules loaded: none.

为什么会这样?我怎样才能使这段代码编译?感谢您的帮助~

我知道了。我调整了代码以查看它的编译:

instance Monad (Either a) where
     return = Right
     Left a >>= f = Left a
     Right x >>= f = f x

它编译成功!但是......还有一个问题:

instance Monad (Either a)

使'Either a'成为一个单子,我得到'return = Right'......我怎么能得到'return = Left'?我试过这个但失败了:

instance Monad (`Either` a) where
     return = Left
     Right a >>= f = Right a
     Left x >>= f = f x

或:实例 Monad (\x -> 任一个 xa)

根本不编译!

4

2 回答 2

9

大多数混淆源于左和右被向后使用的事实。仅考虑返回的类型,其来自 Monad 类型类的类型如下:

return :: (Monad m) => b -> m b

您正在尝试为m=定义一个实例Either a,因此 return 应该具有类型:

return :: b -> Either a b

您将其定义为 Left,其类型为:

Left :: a -> Either a b

请注意左侧的->不同之处。

于 2010-04-06T17:41:37.023 回答
3
  1. return 应该有 type forall b. b -> Either a b,但是 Left 有 type forall c. a -> Either a c。你可能想要就在这里。
  2. fail应该有 type forall b. String -> Either a b,但是 Right 有 type forall b. b -> Either a b,所以如果b=StringString -> Either a String不适合。
  3. >>=应该有 typeEither a b -> (b -> Either a c) -> Either a c但是Right x >>= _ = Right x总是返回 type 的值Either a b,而不是Either a c
  4. Left x >>= f = f x不起作用,因为 x 有 type a,但f有 type b -> c
于 2010-04-06T17:39:11.640 回答