Ho il seguente trasformatore monad per gestire gli errori in Haskell.Monadi Haskell e un errore che non richiede una stringa
instance (Monad m, Error e) => Monad (EitherT e m) where
return = EitherT . return . return
m >>= k = EitherT $ do
a <- runEitherT m
case a of
Left l -> return (Left l)
Right r -> runEitherT (k r)
fail = EitherT . return . Left . strMsg
E funziona abbastanza bene, come posso istanziare Error
con una classe personalizzata e avere un mezzo abbastanza flessibili da cui gestire gli errori.
fail
è un po 'sciocco, però, perché è il tipo String -> EitherT e m
e la restrizione String
può essere un modo fastidioso per creare errori. Io alla fine con un sacco di:
instance Error BazError where
strMsg "foo" = FooError -- oh look we have no error context
strMsg "bar" = BarError -- isn't that nice
Quello che mi piacerebbe fare è creare una nuova funzione, come fail
, che è di tipo a -> e
in modo che possa rimuovere la restrizione (Error e)
. fail
è particolarmente utile quando la pila Monade diventa grande, come quando alla fine con
EitherT BazError (StateT [BazWarning] IO) Foo
C'è un modo per creare una funzione che ha lo stesso comportamento fail
con un tipo meno restrittivo? O è implementato fail
utilizzando la magia dark haskell profonda?
Probabilmente si dovrebbe semplicemente evitare "fail" interamente, a meno che non si voglia personalizzare il comportamento in caso di mancata corrispondenza del modello "do'-block". – ehird