Because I oversimplified in my other question before, I would like to give a more clear example here.
How can I handle situations where I have to check for certian conditions in a sequential way without nesting multiple cases? With “sequential way” I mean getting a value (e.g. from stdin), checking this value for a certain condition and depending on the outcome getting another value and so on.
Example:
sequen :: IO String
sequen = do
a <- getLine
case a of
"hi" -> do
putStrLn "hello!"
b <- getLine
case b of
"how are you?" -> do
putStrLn "fine, thanks"
return "nice conversation"
_ -> return "error 2"
_ -> return "error 1"
I know that there are better ways to write such a chat bot, it should just demonstrate the sequential nature of the problem. As you can see, with every nested case, the code also gets indented deeper.
Is there a way to better structure such code? I’m thinking of handling the “errors” on one place and describing the “success-path” without the error handling distributed all over it.
Of course. This is precisely what
EitherTwas made for. You can get it fromControl.Monad.Trans.Eitherin theeitherTpackage.EitherTaborts the current code block whenever it encounters aleftstatement, and people typically use this to indicate error conditions.The inner block’s type is
EitherT Int IO String. When yourunEitherTit, you getIO (Either Int String). TheLefttype corresponds to the case where it failed with aleftand theRightvalue means it successfully reached the end of the block.