Tengo el siguiente transformador de mónada para tratar los errores en Haskell.Mónadas Haskell y un fallo que no requiere una cadena
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
funciona bastante bien, ya que puedo crear una instancia Error
con una clase personalizada y tener un medio bastante flexibles por lo que para controlar los errores.
fail
es un poco tonto, sin embargo, porque es el tipo String -> EitherT e m
, y la restricción String
puede ser una forma molesta de crear errores. Termino con una gran cantidad de:
instance Error BazError where
strMsg "foo" = FooError -- oh look we have no error context
strMsg "bar" = BarError -- isn't that nice
Lo que me gustaría hacer es crear una nueva función, como fail
, que es de tipo a -> e
para que pueda eliminar la restricción (Error e)
. fail
es especialmente conveniente cuando la pila mónada se hace grande, como cuando termino con
EitherT BazError (StateT [BazWarning] IO) Foo
¿Hay una manera de crear una función que tiene el mismo comportamiento que fail
con un tipo menos restrictivo? ¿O está implementado el fail
usando la magia oscura profunda de Haskell?
Probablemente deberías evitar 'fail' por completo, a menos que quieras personalizar el comportamiento en las coincidencias de patrones' do'-block 'que fallaron. – ehird