Идиоматический способ написать 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)