Frage

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

Dieser Code -Frag in 'baby.hs' verursachte den schrecklichen Kompilierungsfehler:

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.

Warum passiert das? Und wie könnte ich diesen Code kompilieren lassen? Danke für jede Hilfe ~

Aha. Und ich habe den Code angepasst, um ihn zu erstellen:

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

Es kompiliert erfolgreich! Aber ... für eine weitere Frage:

instance Monad (Either a)

macht 'entweder ein' a monad und ich habe 'return = rechts' ... wie könnte ich 'return = links' bekommen? Ich habe es versucht, aber gescheitert:

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

oder: Instanzmonade ( x -> entweder xa)

Kompiliert überhaupt nicht!

War es hilfreich?

Lösung

  1. Rückgabe sollte Typ haben forall b. b -> Either a b, Allerdings hat der Typ forall c. a -> Either a c. Sie wollen wahrscheinlich hier.
  2. fail sollte Typ haben forall b. String -> Either a b, Allerdings hat richtig Typ forall b. b -> Either a b, also wenn b=String das macht String -> Either a String was nicht passt.
  3. >>= sollte Typ haben Either a b -> (b -> Either a c) -> Either a c jedoch Right x >>= _ = Right x Gibt immer einen Wert des Typs zurück Either a b, nicht Either a c.
  4. Left x >>= f = f x Funktioniert nicht, weil x Typ hat a, aber f hat Typ b -> c.

Andere Tipps

Der größte Teil der Verwirrung ergibt sich aus der Tatsache, dass links und rechts nach hinten verwendet werden. In Anbetracht des Typs für die Rückkehr lautet sein Typ aus der Monadentypklasse wie folgt:

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

Sie versuchen, eine Instanz für zu definieren m = Either a, also sollte die Rückgabe einen Typ haben:

return :: b -> Either a b

Sie definieren es als übrig, was einen Typ hat:

Left :: a -> Either a b

Beachten Sie, wie die linke Seite des -> unterscheidet sich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top