2010-04-06 6 views
5
instance Monad (Either a) where 
    return = Left 
    fail = Right 
    Left x >>= f = f x 
    Right x >>= _ = Right x 

ce code dans frag '' baby.hs a causé l'erreur de compilation horriblePourquoi ce type de code monophonique ne vérifie pas?

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. 

pourquoi cela arrive? et comment pourrais-je faire compiler ce code? merci pour toute aide ~

je vois. et j'ai ajusté le code pour le voir compiler:

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

il compile avec succès! mais ... pour une autre question:

instance Monad (Either a) 

fait « Soit un » monade et je suis « retour = droite » ... comment pourrais-je obtenir « retour = gauche »? J'ai essayé cela, mais a échoué:

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

ou: exemple Monad (\ x -> Soit x a)

ne compile pas du tout!

+0

Un article de blog à ce sujet: http://ro-che.blogspot.com/2008/09/haskell-puzzle-either-monad.html –

Répondre

3
  1. retour doit avoir le type forall b. b -> Either a b, mais à gauche est de type forall c. a -> Either a c. Vous voulez probablement juste ici.
  2. fail devrait avoir le type forall b. String -> Either a b, mais le droit a le type forall b. b -> Either a b, donc si b=String cela fait String -> Either a String qui ne correspond pas.
  3. >>= doit avoir le type Either a b -> (b -> Either a c) -> Either a c Cependant Right x >>= _ = Right x renvoie toujours une valeur de type Either a b, pas Either a c.
  4. Left x >>= f = f x ne fonctionne pas car x a le type a, mais f a le type b -> c.
9

La plus grande partie de la confusion provient du fait que Left et Right sont utilisés à l'envers. Considérant que le type de retour, son type de la classe de types Monad est la suivante:

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

Vous essayez de définir une instance pour m = Either a, donc retour doit avoir le type:

return :: b -> Either a b 

vous vous définissez comme à gauche, qui est de type:

Left :: a -> Either a b 

Notez comment le côté gauche du -> diffère.

+0

je vois.et i ajusté le code pour voir compile: exemple Monad (Soit a) où retour = droite gauche une >> = f = gauche un droit x >> = f = f x il compile avec succès! mais ... pour une question supplémentaire: instance Monad (Soit a) fait 'Soit a' une monade et j'ai 'return = Right' ... comment puis-je obtenir 'return = Left'? J'ai essayé cela, mais a échoué: exemple Monad ('Either' a) où = retour gauche droite une >> = f = droite une X gauche >> = f = fx ou: exemple Monad (\ x -> Soit xa) ne compile pas du tout! –

+0

Vous ne pouvez pas faire 'Soit a' une Monade avec' return' = 'Left'. Un Haskell 'Monad' est une typeclass d'un paramètre (prenons' b'), qui correspond au type de l'argument 'return'. Ceci est incompatible avec la définition de Haskell de 'Either', qui est une classe de type où le dernier argument est celui à' Right'. Vous ne pouvez atteindre ce que vous voulez en redéfinissant 'Sither' avec des arguments de type swappés, comme dans' data Soit a b = Left b | Juste a' mais alors vous seriez incompatible avec tout le support de la librairie standard sur les valeurs 'Soit'. –

Questions connexes