Proposal: `(a -> Result x b) -> List a -> Result (List x) (List b)`
adamyakes opened this issue · comments
adamyakes commented
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
If people are interested, I'd be glad to add this in a PR with tests and docs!