haskell - exceptions and monad transformers -
i'm using eithert monad transformer. combining io monad, i'm afraid exception , not caught.
indeed exception passes through:
import control.monad.trans import control.error import system.directory main = runeithert testex >>= print testex :: eithert string io () testex = lift $ removefile "non existing filename" but eithert otherwise fits bill convey callers error. want use that, not throw exceptions...
i looked @ try control.exception:
try :: exception e => io -> io (either e a) it looks want, fit in eithert io stack... (probably added hoisteither , maybe fmapl , starts looking verbose though) naive lift $ try doesn't typecheck.
i'm sure problem has been solved thousands of times, can't find link describing exact issue. how supposed solved?
edit "how supposed solved", interested in idiomatic solution, standard way handle in haskell. answers far, seems idiomatic way let exceptions thown , handle them higher-up. seems bit counter-intuitive have 2 flows of control , return paths, apparently way it's meant done.
you don't want lift trying computation, you'd exception e => eithert io (either e ()).
testex :: (exception e, monadtrans m) => m io (either e ()) testex = lift . try $ fails you don't want error in result, want integrate error eithert. want integrate trying somethign eithert
testex :: (exception e) => eithert e io () testex = eithert . try $ fails we'll in general, message want.
integrate try eithert
you can extract idea of integrating try eithert
tryio :: (exception e) => io -> eithert e io tryio = eithert . try or, underlying monadio as
tryio :: (exception e, monadio m) => io -> eithert e m tryio = eithert . liftio . try (tryio conflicts name control.error. couldn't come name this.)
you can willing catch exception. someexception catch exceptions. if interested in specific exceptions, use different type. see control.exception details. if aren't sure want catch, want catch ioexceptions; tryio control.error does; see last section.
anyexception :: eithert someexception m -> eithert someexception m anyexception = id you want keep error message exception
message :: (show e, functor m) => eithert e m -> eithert string m message = bimapeithert show id then can write
testex :: eithert string io () testex = message . anyexception . tryio $ fails integrate try monaderror
you can instead integrate trying monaderror, using monaderror , monadio penetrate transformer stack.
import control.monad.except tryio :: (monaderror e m, monadio m, exception e) => io -> m tryio = (>>= either throwerror return) . liftio . try you can write testex in terms of tryio , anyexception , message previous section
testex :: eithert string io () testex = message . anyexception . tryio $ fails tryio control.error
the tryio control.error our first tryio, except catches ioexceptions instead of exception. it's defined as
tryio :: (monadio m) => io -> eithert ioexception m tryio = eithert . liftio . try we can use message write testex
testex :: eithert string io () testex = message . tryio $ fails
Comments
Post a Comment