Maybe

type Maybe a = Just a | Nothing
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

type alias Person =
    { name : String
    , age : Maybe Int
    }

tom = { name = "Tom", age = Just 42 }
sue = { name = "Sue", age = Nothing }

withDefault : a -> Maybe a -> a
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"

just as Functor Maybe in Haskell

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

map sqrt (Just 9) == Just 3
map sqrt Nothing == Nothing

map2 : (a -> b -> value) -> Maybe a -> Maybe b -> Maybe value

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

map3 map4 map5

just as Monad Maybe in Haskell

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

its definition:

andThen : (a -> Maybe b) -> Maybe a -> Maybe b
andThen f x =
    case x of
        Just v ->  f v
        Nothing  ->  Nothing

for example, say you need to use (head : List Int -> Maybe Int) to get the first month from a List and then make sure it is between 1 and 12:

toValidMonth : Int -> Maybe Int
toValidMonth m = if m >= 1 && m <= 12 then Just m else Nothing

getFirstMonth : List Int -> Maybe Int
getFirstMonth ms = head ms |> andThen toValidMonth

if head fails and results in Nothing (because the List was empty), 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