Headline

A monad for dealing with partiality or error handling

Illustration

Let us put to work the maybe monad in a simple 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 2)
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)

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. 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 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

We can also define the guard function now which was 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 the 101repo.

Metadata


There are no revisions for this page.

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.

    10 most similar pages:

    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.