Optional values (Maybe)

The type Maybe a can be used in situations where some value can not be necessarily computed. Its values are either Nothing or Just v where the type of v is a.

data Maybe a (Builtin)

Represents an optional value.

Nothing :: Maybe b (Builtin)
Just :: b -> Maybe b (Builtin)
fromJust :: Maybe a -> a (Prelude)

Given Just x this function returns x. If the parameter is Nothing, the function raises an exception.

fromMaybe :: a -> Maybe a -> a (Prelude)

fromMaybe def v returns def if v=Nothing and x if v=Just x.

execJust :: Maybe a -> (a -> <c> b) -> <c> () (Prelude)

execJust v f executes the function f with parameter value x, if v=Just x. If v=Nothing, the function does nothing.

filterJust :: [Maybe a] -> [a] (Prelude)

Takes those elements of the input list that match (Just x) and adds the contents to the resulting list. For example,

filterJust [Just 1, Nothing, Just 5] = [1, 5]
orElse :: Maybe a -> <b> a -> <b> a (Prelude)

Provides a default value if the first parameter is Nothing. The default value is evaluated only if needed. The function can be used as an operator and is right associative so that the following is possible:

tryWithTheFirstMethod
    `orElse` tryWithTheSecondMethod
    `orElse` fail "Didn't succeed."
elemMaybe :: a -> Maybe a -> Boolean (Prelude)

elemMaybe v1 (Just v2) returns true if v1 == v2. elemMaybe v1 Nothing is always false.

When to use Maybe vs exceptions

Prefer Maybe when:

  • Absence of a value is a normal, expected outcome (e.g. looking up a key that may not exist, parsing user input that might be malformed).
  • The caller needs to distinguish between "value found" and "value not found" without catching an exception.

Use exceptions / runtime errors when the absence signals a programming error — for example, fromJust Nothing throws an exception and is appropriate only when you are certain the value is Just.

Maybe as a monad

Maybe forms a monad: a chain of operations where any step may produce Nothing, and the entire chain short-circuits to Nothing as soon as that happens. This avoids nested match expressions:

// Without monad:
lookupFullName db firstName =
    match lookup firstName db with
        Nothing   -> Nothing
        Just last -> match lookup last db with
            Nothing    -> Nothing
            Just full  -> Just full

// With mdo:
lookupFullName db firstName = mdo
    last <- lookup firstName db
    full <- lookup last db
    return full

The mdo block desugars to >>= (bind) chains. If any step yields Nothing, the remainder is skipped and the whole expression returns Nothing.

Either — errors with a reason

Either A B is a two-constructor type:

data Either a b = Left a | Right b

By convention, Left carries an error value and Right carries a success value. Use Either when you need to return a failure reason alongside a possible result:

safeDivide :: Double -> Double -> Either String Double
safeDivide _ 0.0 = Left "division by zero"
safeDivide x y   = Right (x / y)

match safeDivide 10.0 0.0 with
    Left err  -> print "Error: \(err)"
    Right val -> print "Result: \(val)"

Either is also a monad (binding on Right, short-circuiting on Left), which makes it suitable for chaining fallible operations in a mdo block.