Идиоматический способ написать firstRightOrLefts в Haskell?

У меня есть следующий метод:

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

Меня беспокоит уродливое сопоставление шаблонов, и мне было интересно, есть ли более идиоматический способ написать этот метод. Идея в том, что у меня есть множество вычислений, которые могут вернуть Эйтерса, и я просто хочу получить первый результат или все сообщения об ошибках. Возможно, я использую неправильную структуру данных. Возможно, писательская монада лучше подходит для этой задачи. На данный момент я действительно не уверен. Приветствия за любую помощь!

Ответ 1

Обратное соглашение - это просто определение монады для Either, и определение для sequence подходит для этого:

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

Чтобы применить это к вашему случаю, нам нужна функция flipEither:

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

Ответ 2

Экземпляр MonadPlus для Except имеет следующее поведение:

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

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