Perché questo codice a entrambi i monadi non digita il controllo?
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!
Soluzione
- Il ritorno dovrebbe avere il tipo
forall b. b -> Either a b
, comunque a sinistra ha il tipoforall c. a -> Either a c
. Probabilmente vuoi proprio qui. fail
dovrebbe avere il tipoforall b. String -> Either a b
, Tuttavia, il giusto ha il tipoforall b. b -> Either a b
, quindi seb=String
quello faString -> Either a String
che non si adatta.>>=
dovrebbe avere il tipoEither a b -> (b -> Either a c) -> Either a c
peròRight x >>= _ = Right x
restituisce sempre un valore di tipoEither a b
, nonEither a c
.Left x >>= f = f x
non funziona perché x ha un tipoa
, maf
ha un tipob -> 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.