2010-04-06 43 views
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) 

使得“无论是”一个单子,我得到了“回报=右” ...我怎么能得到“回报=左”? 我已经尝试过这一点,但失败:

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

或: 实例单子(\ X - >中X一)

不编译了!

+0

关于此问题的博客文章:http://ro-che.blogspot.com/2008/09/haskell-puzzle-either-monad.html – 2010-04-06 17:44:58

回答

3
  1. 返回应该有类型forall b. b -> Either a b,但左有类型forall c. a -> Either a c。你可能想在这里。
  2. fail应该有类型forall b. String -> Either a b,但是右键有forall b. b -> Either a b,所以如果b=String那使得String -> Either a String哪个不适合。
  3. >>=的类型应该是Either a b -> (b -> Either a c) -> Either a c然而Right x >>= _ = Right x总是返回类型Either a b,不Either a c的值。
  4. Left x >>= f = f x不起作用,因为x的类型为a,但f的类型为b -> c
9

大部分的困惑都来自左侧和右侧的事实。如果仅考虑回国的类型,从单子类型类的类型如下:

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

你试图定义m = Either a一个实例,所以返回的类型应该是:

return :: b -> Either a b 

你将其定义为左,其类型为:

Left :: a -> Either a b 

注意如何->不同的左手边。

+0

我明白了。我调整了代码,看看它编译: 实例单子(可能是),其中 收益率=右 左一个>> = F =左一个右 >> X = F = F X 它编译成功! 但是...对于另一个更多的问题: 实例Monad(或者a) 使'任一个'单子,我得到'返回=右'...我怎么能'返回=左'? 我已经尝试过这一点,但失败: 实例单子('Either' a)凡 收益率=左 权>> = F =右一左 >> X = F = FX 或: 实例单子(\ x - > xa) 根本不编译! – 2010-04-07 15:45:31

+0

你不能用'return' ='Left'使''a''成为Monad。 Haskell'Monad'是一个参数的类型类型(让我们看一下'b'),它与'return'参数的类型匹配。这与Haskell对'Either'的定义是不兼容的,这是一个类型类,其中最后一个参数是'Right'的类型。你只能通过使用交换类型参数重新定义'Either'来实现你想要的,就像在'data'中一样b = Left b |正确的一个',但是你会不符合'Either'值的所有标准库的支持。 – 2010-04-07 16:05:31