简体   繁体   中英

Short-circuit list, type of `(a -> Either e a) -> [a] -> Either e [a]` ... monadic operation?

Consider the following function:

validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList validate []     = Right []
validateList validate (x:xs) =
    case validate x of
      Left err -> Left err
      Right y  -> case validateList validate xs of
                    Left err -> Left err
                    Right ys -> Right $ y:ys

Is there a way to write this in a more concise way? Maybe using the >>= operator?

A bit to think about because there are actually two monads here: [] and Either , although List here is not acting as a monad but just more so as a Traversable

I believe your Traversable idea is exactly what you need.

validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList = traverse

This is traverse using the Either a applicative functor and the [] traversable/foldable.

Note that this does indeed lazy/short-circuiting: as soon as a Left is found the rest of the input list is no longer demanded. Here is a test using an infinite list:

> validateList (\n -> case n of 1 -> Right 56 ; 2 -> Left "fdsf") [1..]
Left "fdsf"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM