I would like to combine the Error Monad and the IO Monad in Haskell. Here is an excerpt from my code:
type AskMonad = ErrorT String IO
askSomething :: AskMonad Direction
askSomething = do
liftIO $ putStrLn "Choose an element from the list [1,2,3,4]"
input <- liftIO getLine
let entry = read input :: Int
if entry `elem` [1,2,3,4]
then return $ toEnum entry -- from Int to Direction
else throwError "Invalid input!"
selectMove :: [Player] -> Board -> IO (Direction, Position)
selectMove players board = do
direction <- runErrorT (askSomething) `catchError` --What to put here???
-- Other IO stuff...
I would like to achieve the following behavior:
- if
askSomethingsucceeds, get theDirection. - if
askSomethingfails,showthe error and runaskSomethingagain.
However, I don't know what to put as the second argument of catchError in order to get this behavior. I think it should be of the following type signature: Either String Direction -> AskMonad Direction, but how can I access the computation that needs to be rerun (askSomething in this case).
The code as you have it now seems like it would be trying to catch exceptions not represented in the
ErrorT Stringresult. My thought is that you are actually looking to retry ifrunErrorTresults in aLeftvalue (an "expected" exception). In that case, something like thisretryForevermay work:which could be used like:
P.S. I believe
ErrorTwas deprecated in favor ofExceptT, and thatExceptTis only more general so the transition should be trivial if you decide to switch.