You know how many packages have map
, map2
, map3
, etc functions? For example Maybe
, Result
and Json.Decode
.
Such packages usually also have an andThen
function.
Have you ever needed andThen2
? I did the other day, and learned how to do it.
Here’s the trick:
- Use
map2
as if it wasandThen2
. (Pretend it is.) - Pipe to
andThen identity
.
So how does that work? map2
will give a nested structure. andThen identity
flattens it.
On to an example. Array.get
returns a Maybe
. Since I do that inside a map
(map2
), we end up with a Maybe inside a Maybe:
x : Maybe (Maybe Int)
x =
Maybe.map2
(\one two -> Array.get (one + two) (Array.fromList [ 1, 2, 3, 4 ]))
(String.toInt "1")
(String.toInt "2")
Maybe.andThen identity
flattens it:
x : Maybe Int
x =
Maybe.map2
(\one two -> Array.get (one + two) (Array.fromList [ 1, 2, 3, 4 ]))
(String.toInt "1")
(String.toInt "2")
|> Maybe.andThen identity
Why? Because the function you give to Maybe.andThen
takes something, and must return a new Maybe. But unlike map
, andThen
does not produce a nested structure. It flattens. (It’s sometimes called flatMap
in other languages.)
In the above example, andThen
’s function will receive a Maybe Int
as input. Since I used identity
as that function, it will return the same Maybe Int
. And that’s a Maybe, just like Maybe.andThen
requires us to return. And now andThen
will flatten for us, like it always does.
This trick works for any container kind of type that has map2
and andThen
. It also works for map3
and up
I thought this was a really neat trick for the times you end up needing andThen2
, and I learned a lot from it. Hope this can be useful to somebody else too!