Question

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

Ce code de code dans «baby.hs» a provoqué l'horrible erreur de compilation:

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-t-il? Et comment pourrais-je faire compiler ce code? Merci pour toute aide ~

Je vois. Et j'ai ajusté le code pour le voir compile:

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 nouvelle question:

instance Monad (Either a)

Fait «un« a »une monade et j'ai obtenu» return = droite »... comment pourrais-je obtenir« retour = gauche »? J'ai essayé cela mais j'ai échoué:

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

ou: instance monad ( x -> soit xa)

ne compile pas du tout!

Était-ce utile?

La solution

  1. Le retour doit avoir le type forall b. b -> Either a b, Cependant, la gauche a le type forall c. a -> Either a c. Vous voulez probablement ici.
  2. fail devrait avoir le type forall b. String -> Either a b, Cependant, la bonne a le type forall b. b -> Either a b, donc si b=String qui fait String -> Either a String ce qui ne convient pas.
  3. >>= devrait avoir le type Either a b -> (b -> Either a c) -> Either a c toutefois Right x >>= _ = Right x Renvoie toujours une valeur de type Either a b, ne pas Either a c.
  4. Left x >>= f = f x ne fonctionne pas parce que x a le type a, mais f a le type b -> c.

Autres conseils

La plupart de la confusion provient du fait que la gauche et la droite sont utilisées à l'envers. Compte tenu uniquement du type de retour, son type de la TypeClass de Monad est le suivant:

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

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

return :: b -> Either a b

Vous le définissez comme à gauche, qui a le type:

Left :: a -> Either a b

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top