Maybe

This library fills a bunch of important niches in Gren. A Maybe can help you with optional arguments, error handling, and records with optional fields.

type Maybe a
= Just a
| Nothing

Represent values that may or may not exist. It can be useful if you have a record field that is only filled in sometimes. Or if a function takes a value sometimes, but does not absolutely need it.

-- A person, but maybe we do not know their age.
type alias Person =
    { name : String
    , age : Maybe Int
    }

tom =
    { name = "Tom", age = Just 42 }

sue =
    { name = "Sue", age = Nothing }

Queries

hasValue : a -> Maybe a -> Bool

Checks to see if the Maybe is Just, and that the contained value equals a provided constant.

hasValue 5 (Just 5) == True

hasValue 5 (Just 3) == False

hasValue 5 Nothing == False
checkValue : (a -> Bool) -> Maybe a -> Bool

Checks to see if the Maybe is Just, and that the contained value passes the provided test.

checkValue isOdd (Just 5) == True

checkValue isOdd (Just 2) == False

checkValue isOdd Nothing == False
keepIf : (a -> Bool) -> Maybe a -> Maybe a

Returns Nothing if the contained value doesn't pass the given test.

keepIf isOdd (Just 5) == Just 5

keepIf isOdd (Just 2) == Nothing

Transform

withDefault : a -> Maybe a -> a

Provide a default value, turning an optional value into a normal value. This comes in handy when paired with functions like Dict.get which gives back a Maybe.

withDefault 100 (Just 42) == 42

withDefault 100 Nothing == 100

withDefault "unknown" (Dict.get "Tom" Dict.empty) == "unknown"
withDefaultLazy : ({} -> a) -> Maybe a -> a

Same as withDefault but the default value is wrapped in a function. This is useful when computing the default value is expensive, as you can compute it only when it is required.

In most cases you should use pattern matching or withDefault instead.

map : (a -> b) -> Maybe a -> Maybe b

Transform a Maybe value with a given function:

map sqrt (Just 9) == Just 3

map sqrt Nothing == Nothing

map sqrt (String.toFloat "9") == Just 3

map sqrt (String.toFloat "x") == Nothing
map2 : (a -> b -> value) -> Maybe a -> Maybe b -> Maybe value

Apply a function if all the arguments are Just a value.

map2 (+) (Just 3) (Just 4) == Just 7

map2 (+) (Just 3) Nothing == Nothing

map2 (+) Nothing (Just 4) == Nothing

map2 (+) (String.toInt "1") (String.toInt "123") == Just 124

map2 (+) (String.toInt "x") (String.toInt "123") == Nothing

map2 (+) (String.toInt "1") (String.toInt "1.3") == Nothing
map3 :
(a -> b -> c -> value)
-> Maybe a
-> Maybe b
-> Maybe c
-> Maybe value
map4 :
(a -> b -> c -> d -> value)
-> Maybe a
-> Maybe b
-> Maybe c
-> Maybe d
-> Maybe value
map5 :
(a -> b -> c -> d -> e -> value)
-> Maybe a
-> Maybe b
-> Maybe c
-> Maybe d
-> Maybe e
-> Maybe value
andThen : (a -> Maybe b) -> Maybe a -> Maybe b

Chain together many computations that may fail. It is helpful to see its definition:

andThen : (a -> Maybe b) -> Maybe a -> Maybe b
andThen callback maybe =
    when maybe is
        Just value ->
            callback value

        Nothing ->
            Nothing

This means we only continue with the callback if things are going well. For example, say you need to parse some user input as a month:

parseMonth : String -> Maybe Int
parseMonth userInput =
    String.toInt userInput
        |> andThen toValidMonth

toValidMonth : Int -> Maybe Int
toValidMonth month =
    if 1 <= month && month <= 12 then
        Just month

    else
        Nothing

In the parseMonth function, if String.toInt produces Nothing (because the userInput was not an integer) this entire chain of operations will short-circuit and result in Nothing. If toValidMonth results in Nothing, again the chain of computations will result in Nothing.