elm-community / list-extra

Convenience functions for working with List.
http://package.elm-lang.org/packages/elm-community/list-extra/latest
MIT License
135 stars 58 forks source link

Proposal: `(a -> Result x b) -> List a -> Result (List x) (List b)` #178

Open adamyakes opened 5 months ago

adamyakes commented 5 months ago

I've found myself writing this function a couple times. It's a map that collects all failures. If every call to f returns Ok, the result is Ok (List b), but if one or more fail, the result is Err (List x). The implementation is straightforward, but I'm not sold on a name

collectResults : (a -> Result x b) -> List a -> Result (List x) (List b)
collectResults f =
    let
        folder a res =
            case (f a, res) of
                (Ok b, Ok bs) ->
                    Ok (b :: bs) -- Collect more Ok's
                (Ok _, Err xs) ->
                    Err xs -- Ok's are ignored once we hit an error
                (Err x, Ok _) ->
                    Err [x] -- One Err causes the whole thing to Err
                (Err x, Err xs) ->
                    Err (x :: xs) -- Collect more Err's
    in
    List.foldr folder (Ok [])

The function is useful when checking a bunch of input, and only passing the whole thing if all is good, but collecting (multiple) errors to show if any are bad.

adamyakes commented 5 months ago

If people are interested, I'd be glad to add this in a PR with tests and docs!