Robert Massaioli
Robert Massaioli

Reputation: 13487

Idiomatic way to write firstRightOrLefts in Haskell?

I have the following method:

firstRightOrLefts :: [Either b a] -> Either [b] a
firstRightOrLefts eithers = 
   case partitionEithers eithers of
      (_,  (x : _)) -> Right x
      (xs, _)       -> Left xs

What bothers me is the ugly pattern matching and I was wondering if there was a more idiomatic way to write this method. The idea is that I have a bunch of computations that can return Eithers and I just want to get the first result or all of the error messages. Maybe I'm using the wrong data structure. Maybe the Writer monad would be better suited to this task. I'm really not sure at this point. Cheers for any help!

Upvotes: 10

Views: 290

Answers (2)

CR Drost
CR Drost

Reputation: 9817

The reverse convention is actually just the monad definition for Either and the definition for sequence is adequate for this:

ghci> :t sequence :: [Either a b] -> Either a [b]
sequence :: [Either a b] -> Either a [b]
  :: [Either a b] -> Either a [b]

To actually apply this to your case we'd therefore need a function flipEither:

firstRightOrLefts = fe . sequence . map fe
    where fe (Left a) = Right a
          fe (Right b) = Left b

Upvotes: 18

danidiaz
danidiaz

Reputation: 27766

The MonadPlus instance for Except has this behaviour:

import Control.Monad
import Control.Monad.Trans.Except

firstRightOrLefts :: [Either e a] -> Either [e] a
firstRightOrLefts = runExcept . msum . fmap (withExcept (:[]) . except)

Upvotes: 9

Related Questions