Home > database >  Short-circuit list, type of `(a -> Either e a) -> [a] -> Either e [a]` ... monadic operatio
Short-circuit list, type of `(a -> Either e a) -> [a] -> Either e [a]` ... monadic operatio

Time:07-10

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

CodePudding user response:

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"
  • Related