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

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

jsf - How to ajax update an item in the footer of a PrimeFaces dataTable? -

django - CSRF verification failed. Request aborted. CSRF cookie not set -