Open skyqrose opened 5 years ago
An alternative implementation (and also a way to work around the lack of this) is with something like map2 f decoderA decoderB |> andThen identity
, where andThen identity
is a way to implement join : Decoder (Decoder a) -> Decoder a
.
In my personal projects, I prefer using a pipeline-style of decoding, so I'm likely to end up writing this like so:
decoder : Decoder (List ( Int, String ))
decoder =
Decode.succeed zip
|> Decode.andMap (Decode.field "ids" (Decode.list Decode.int))
|> Decode.andMap (Decode.field "names" (Decode.list Decode.string))
|> Decode.andThen identity
-- Couldn't help myself and had to turn this into a tail recursive thing
zip : List a -> List b -> Decoder (List ( a, b ))
zip left right =
zipHelper left right []
zipHelper : List a -> List b -> List ( a, b ) -> Decoder (List ( a, b ))
zipHelper left right acc =
case ( left, right ) of
( [], [] ) ->
Decode.succeed (List.reverse acc)
( x :: xs, y :: ys ) ->
zipHelper xs ys (( x, y ) :: acc)
( _, _ ) ->
Decode.fail "Expected lists of equal length"
So, I'm torn. On the one hand, it takes some insight to realize map2 + join
is andThen2
(in the same way that map + join = andThen
), whereas andThenX
is fairly obvious. On the other hand, adding a join
at the end makes this easily usable with all mapX
and andMap
sort of deals, without needing a whole bunch of functions to cover the spectrum. Finally, there is precedent for having a join
function for pipeline style decoding 🤔
Long story short, I'm curious how knowing about the andThen identity
trick might change your thoughts on this?
map2 Tuple.pair
is how I would implement it. Would we want andThen3
and so on?
For combining multiple decode results in a way that might fail.
E.g if you have json that looks like
and you want to zip the two lists together, but fail if they're different lengths, you could do
Can be implemented as something like
It's simple enough to use the tuple everywhere, but it reads a little better to be able to say
andThen2
instead.