Reputation: 1389
I've been running into a frequent issue in elm where I have a function that depends on multiple maybe values being Just. Is there a less verbose way to write this code:
commandIf apples bananas oranges =
case apples of
Just apples_ ->
case bananas of
Just bananas_ ->
case oranges of
Just oranges_ ->
someCommand apples_ bananas_ oranges_
Nothing ->
Cmd.none
Nothing ->
Cmd.none
Nothing ->
Cmd.none
Upvotes: 10
Views: 1936
Reputation: 85442
Maybe.map3
solves your particular case, but this answer is about the general pattern of chaining maybe values using Maybe.andThen
.
commandIf a_ b_ c_ =
a_ |> Maybe.andThen (\a ->
b_ |> Maybe.andThen (\b ->
c_ |> Maybe.andThen (Just << someCommand a b)))
|> Maybe.withDefault Cmd.none
Upvotes: 1
Reputation: 14101
@laughedelic's answer is very good. Just wanted to offer some alternative and more generic solutions too, since verbose Maybe
unwrapping is an issue I also ran into when I started out in Elm.
If you have a fixed number of Maybe
values, you can use map2, map3
etc to do what you want (docs here):
commandIf apples bananas oranges =
Maybe.map3 someCommand apples bananas oranges
|> Maybe.withDefault Cmd.none
Here, someCommand
is your functions that takes 3 arguments, and returns a some command.
Maybe.map3
applies this function only if all 3 variables are Just x
, and wraps it in one Maybe
type. So the result is Just (someCommand apples bananas oranges)
if all 3 have a value. Otherwise, the function returns Nothing
.
This result is then "piped" into Maybe.withDefault
. Which returns a Cmd.none
if the input is Nothing
, and otherwise returns the value (your command), without the Just
.
If you would have a list of Maybe
values of unknown length, you could do something this:
keepOnlyJusts : List (Maybe a) -> List a
keepOnlyJusts listOfMaybes =
listOfMaybes
|> List.filterMap identity
newList = keepOnlyJusts [ Just 1, Nothing, Just 3 ] -- == [1,3]
where the result is a list (could be empty) where only the values are kept.
Upvotes: 11
Reputation: 6460
If you need all three values at the same time you can match them together as a tuple and leave all other combinations (when one of them or several are Nothing
) to the fallback case:
commandIf apples bananas oranges =
case (apples, bananas, oranges) of
(Just apples_, Just bananas_, Just oranges_) ->
someCommand apples_ bananas_ oranges_
_ ->
Cmd.none
Upvotes: 12