haskell - Monads in monad transformer context -


i have trouble gripping monads , monad transformers. have following contrived example (not compilable):

import control.monad import control.monad.error import control.monad.reader  data state = state int int int type foo = readert state io  readeither :: string -> either string int readeither s = let p = reads s            in case p of                [] -> throwerror "could not parse"                [(a, _)] -> return  readeithert :: io (either string int) readeithert = let p s = reads s           in runerrort $     l <- liftio (getline)     readeither l  foo :: foo int foo =   d <- liftio $ readeithert   case d of        right dd -> return dd        left em ->      liftio $ putstrln em      return (-1)  bar :: foo string bar =   liftio $ getline  defaults = state 0 0 0 

if copy functionality of readeither readeithert, works, have nagging feeling can leverage power of existing readeither function, can't figure out how. if try lift readeither in readeithert function, lifts errort string io (either string int) should. should somehow errort string io int.

if i'm going wrong direction this, correct way handle errors require io (or other monads) , called monadic context (see foo function in example)

edit: apparently not clear trying do. maybe following function describes , why wondering

maybepulsequit :: handle -> io (either string ()) maybepulsequit h = runerrort $   f <- liftio $ (communicate h "finished" :: io (either string bool))   (errort . pure) f >>= \b → liftio $ when b $ liftio pulsequit 

this works, still ugly because of binds. lot clearer previous version had case checking. recommended way this?

it not clear why need errort. can implement readeithert like

readeithert :: io (either string int) readeithert = fmap readeither getline 

if need errort reason, can create utility function eithertoerrort:

eithertoerrort = errort . pure  readeithert = runerrort $   l <- liftio $ getline   eithertoerrort $ readeither l 

[add] maybe want add errort monad stack...

data state = state int int int type foo = errort string (readert state io)  runfoo :: foo -> state -> io (either string a) runfoo foo s = runreadert (runerrort foo) s  doit :: int -> foo int doit = if < 0             throwerror "i < 0"             else return (i * 2) 

example:

*main> runfoo (doit 1 >>= doit) (state 0 0 0) right 4 *main> runfoo (doit (-1) >>= doit) (state 0 0 0) left "i < 0" 

Comments

Popular posts from this blog

android - Spacing between the stars of a rating bar? -

aspxgridview - Devexpress grid - header filter does not work if column is initially hidden -

c# - How to execute a particular part of code asynchronously in a class -