Headline

A monad for dealing with partiality or error handling

Illustration

Let us put to work the Maybe monad in a simple interpreter.

A baseline interpreter

There are these expression forms for floats, addition, and square roots:

-- Simple arithmetic expressions
data Expr = Constant Float | Add Expr Expr | Sqrt Expr
  deriving (Eq, Show, Read)

Consider these samples:

-- Sample terms
sample = Sqrt (Constant 4)
sample' = Sqrt (Constant (-1))

The first expression should evaluate to 2.0. Evaluation should somehow fail for the second one. The most straightforward interpreter may be this one:

-- A straightforward interpreter
eval :: Expr -> Float
eval (Constant f) = f
eval (Add e1 e2) = eval e1 + eval e2
eval (Sqrt e) = sqrt (eval e)

Adding error handling to the interpreter

This interpreter would return NaN (not a number) for the second sample. This is suboptimal if we want to represent the error situation explicitly as an error value so that we cannot possibly miss the problem and it is propagated properly. To this end, we may use a Maybe type in the interpreter as follows:

-- An interpreter using a Maybe type for partiality
eval' :: Expr -> Maybe Float
eval' (Constant f) = Just f
eval' (Add e1 e2) = 
  case eval' e1 of
    Nothing -> Nothing
    Just f1 ->
      case eval' e2 of
        Nothing -> Nothing 
        Just f2 -> Just (f1 + f2)
eval' (Sqrt e) =
  case eval' e of
    Nothing -> Nothing
    Just f -> if f < 0.0
                then Nothing
                else Just (sqrt f)

Alas, the resulting interpreter is harder to understand. Maybes need to be handled for all subexpressions and the intention of propagating Nothing is expressed time and again.

Monadic style

By conversion to monadic style, we can hide error handling:

-- A monadic style interpreter
evalM :: Expr -> Maybe Float
evalM (Constant f) = return f
evalM (Add e1 e2) =
  evalM e1 >>= \f1 ->
  evalM e2 >>= \f2 ->
  return (f1 + f2)
evalM (Sqrt e) =
  evalM e >>= \f ->
  guard (f >= 0.0) >>
  return (sqrt f)

We can also use do notation:

-- A monadic style interpreter in do notation
evalM' :: Expr -> Maybe Float
evalM' (Constant f) = return f
evalM' (Add e1 e2) = do
  f1 <- evalM' e1
  f2 <- evalM' e2
  return (f1 + f2)
evalM' (Sqrt e) = do
  f <- evalM' e
  guard (f >= 0.0)
  return (sqrt f)

The Maybe monad

The Maybe monad is readily provided by the Haskell library, but we may want to understand how it might have been implemented. The corresponding instance of the type class Monad follows:

-- Monad instance for Maybe
instance Monad Maybe
  where
    return = Just
    Nothing >>= f = Nothing
    (Just x) >>= f = f x

The definition of return conveys that a pure computation is successful. The definition of bind conveys that Nothing for the first argument is to be propagated. The Maybe monad actually is a more special monad, i.e., a monad with + and 0:

-- Type class MonadPlus (see Control.Monad)
class Monad m => MonadPlus m
  where
    mzero :: m a
    mplus :: m a -> m a -> m a

-- MonadPlus instance for Maybe
instance MonadPlus Maybe
  where
    mzero = Nothing
    Nothing `mplus` y = y
    x `mplus` _ = x

The Haskell library provides the guard function, which we used in the interpreter:

-- Succeed or fail 
guard :: MonadPlus m => Bool -> m ()
guard b = if b then return () else mzero

In modern Haskell, we also need to make Maybe an instance of Applicative (for applicative functors and Functor (for functors). This code is omitted here, but see GitHub for this page.


Ralf Lämmel edited this article at Sun, 21 Jun 2020 13:19:55 +0200
Compare revisions Compare revisions

User contributions

    This user never has never made submissions.

    User edits

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.

    Syntax for editing wiki

    For you are available next options:

    will make text bold.

    will make text italic.

    will make text underlined.

    will make text striked.

    will allow you to paste code headline into the page.

    will allow you to link into the page.

    will allow you to paste code with syntax highlight into the page. You will need to define used programming language.

    will allow you to paste image into the page.

    is list with bullets.

    is list with numbers.

    will allow your to insert slideshare presentation into the page. You need to copy link to presentation and insert it as parameter in this tag.

    will allow your to insert youtube video into the page. You need to copy link to youtube page with video and insert it as parameter in this tag.

    will allow your to insert code snippets from @worker.