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
map2as 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!