Domanda

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

Questo codice frag in "baby.hs" ha causato l'orribile errore di compilazione:

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.

Perché questo accade? E come potrei realizzare questo codice? Grazie per qualsiasi aiuto ~

vedo. e ho regolato il codice per vederlo compilando:

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

Compila con successo! Ma ... per ulteriori domande:

instance Monad (Either a)

rende 'o una' una monade e ho ottenuto 'return = a destra' ... come potrei ottenere 'return = a sinistra'? L'ho provato ma fallito:

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

o: istanza monade ( x -> o xa)

non si compila affatto!

È stato utile?

Soluzione

  1. Il ritorno dovrebbe avere il tipo forall b. b -> Either a b, comunque a sinistra ha il tipo forall c. a -> Either a c. Probabilmente vuoi proprio qui.
  2. fail dovrebbe avere il tipo forall b. String -> Either a b, Tuttavia, il giusto ha il tipo forall b. b -> Either a b, quindi se b=String quello fa String -> Either a String che non si adatta.
  3. >>= dovrebbe avere il tipo Either a b -> (b -> Either a c) -> Either a c però Right x >>= _ = Right x restituisce sempre un valore di tipo Either a b, non Either a c.
  4. Left x >>= f = f x non funziona perché x ha un tipo a, ma f ha un tipo b -> c.

Altri suggerimenti

La maggior parte della confusione deriva dal fatto che sinistra e destra sono usati all'indietro. Considerando solo il tipo per il ritorno, il suo tipo dalla macchina da tipo di monadi è il seguente:

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

Stai cercando di definire un'istanza per m = Either a, quindi il ritorno dovrebbe avere il tipo:

return :: b -> Either a b

Lo stai definendo come a sinistra, che ha il tipo:

Left :: a -> Either a b

Nota come il lato sinistro del -> differisce.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top