I\'m trying to better understand how to handle error cases in haskell and made wrote some code to help me with that.
Is there a better way (more elegant, sho
Nested Maybes
is indeed messy.
Either
data MyError = ReadError | TooBig Int
explain :: MyError -> String
explain ReadError = "Error: the requested Int could not be found"
explain TooBig i = "Error: the supplied Int should be at most 10, but it was " ++ show i
Now use Either to mix Ok values (Right) and error values (Left):
type MyType = Either MyError Int
Now lots of handy functions like either
and the Applicative and Monad instances for Either a
make it easy to write nice code:
myAdd :: MyType -> MyType -> MyType
myAdd i1 i2 = (+) <$> i1 <*> i2
is nicely applicative, or
myMult i1 i2 = do
a <- i1
b <- i2
return $ a * b
if you prefer monadic notation.
We can use either
in a crash-the-program way
myShow :: MyType -> String
myShow = either (error.explain) show
or a tell-me-anyway way:
process4 :: MyType -> String
process4 = either explain show
data MyType' = OK Int | ReadError | TooBig Int
and use pattern matching. This isn't as nice as suggestion 1 in my veiw, because you lose the higher order function reuse, but it's better than Maybe (Maybe Int)
Read up about Control.Monad.Error and use the supplied functions or the ErrorT
monad transformer.
I think the most readable way is the maybe
function you already tried, just a little bit prettified by avoiding lambdas (pointfree style) and using maybe
even for the innermost check (by replacing if
with mfilter
):
import Control.Monad(mfilter)
process2 :: MyType -> String
process2 =
maybe "error" $
maybe "error2" $
maybe "error3"
show . mfilter (<10) . Just