risposta breve è: Sostituire Error
dal nulla, sostituire ErrorT
da ExceptT
, e le cose dovrebbero continuare a funzionare finché non si utilizza Error
s metodi, fail
(che ora ha una diversa definizione), o, in mancanza pattern corrisponde alla notazione do
.
La differenza essenziale tra il vecchio sistema Control.Monad.Error
e il nuovo sistema Control.Monad.Except
è che il nuovo sistema impone alcuna restrizione classe del tipo di errore/eccezione.
È stato rilevato che la possibilità di utilizzare qualsiasi tipo di errore/eccezione, in modo polimorfico, era più utile della capacità un po 'hacky di personalizzare la conversione dei messaggi di errore stringa.
Quindi la classe Error
è semplicemente scomparsa.
Come effetto collaterale, fail
per ExceptT
ora viene rimosso dalla monade sottostante. Ciò cambia anche l'effetto dei modelli non riusciti nella notazione do
.
La vecchia definizione era:
fail msg = ErrorT $ return (Left (strMsg msg))
che credo sia equivalente a
fail msg = throwError (strMsg msg)
Se hai ancora bisogno di questo comportamento, è possibile utilizzare invece
throwError yourIntendedErrorValue
(throwE
opere invece se stai utilizzando transformers
(ovvero Control.Monad.Trans.Except
) piuttosto che mtl
.)
Il vecchio modello do
mancata corrispondenza si applicherebbe a cose come
do
Just x <- myErrorTAction
...
quando l'azione in realtà restituisce Nothing
. Questo è più imbarazzante, ma potresti ad es.sostituirlo con un case
partita esplicito (essenzialmente Dezuccheraggio esso):
do
y <- myErrorTAction
case y of
Nothing -> throwE ...
Just x -> do
...
@DanielWagner suggerisce la seguente per evitare il rientro in più:
do
x <- myErrorTAction >>= maybe (throwError ...) return
...
La rimozione di Error
elimina anche la necessità di una contraddizione nella denominazione quello Control.Monad.Error
aveva: La maggior parte dei trasformatori segue la regola che SomethingT
è il nome del trasformatore e Something
è un alias di tipo per SomethingT ... Identity
. Il vecchio ErrorT
si è rotto perché la classe Error
è stata utilizzata per qualcosa di completamente diverso.
Nel nuovo sistema, Except e = ExceptT e Identity
, come per altri trasformatori.
hai detto che 'fail' funziona in modo diverso ora, potresti fornire un esempio di come fosse e di come sarebbe stato necessario scrivere codice equivalente? –
@ElectricCoffee Ho espanso quel bit. –
@ ØrjanJohansen Un altro pattern che ho usato occasionalmente: 'do {y <- myErrorTAction >> = forse (throwError ...) return; ...} '. Evita di dover aggiungere un livello di indentazione e può essere adattato ad altre corrispondenze di pattern; per esempio. 'do {y_ <- myErrorTAction; y <- caso y_ di {Nothing -> throwError ...; Solo v -> return v}; ...} 'che aggiunge uno strato di indentazione ma solo temporaneamente (cioè non richiederebbe un rientro annidato se si desidera eseguire due corrispondenze di pattern). –