10

我有以下方法:

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

困扰我的是丑陋的模式匹配,我想知道是否有更惯用的方法来编写这种方法。这个想法是我有一堆可以返回 Eithers 的计算,我只想得到第一个结果或所有错误消息。也许我使用了错误的数据结构。也许 Writer monad 更适合这项任务。在这一点上我真的不确定。为任何帮助干杯!

4

2 回答 2

18

反向约定实际上只是 monad 的定义,Either而 for 的定义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
于 2014-11-05T20:13:18.887 回答
9

MonadPlus实例Except具有这种行为:

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

firstRightOrLefts :: [Either e a] -> Either [e] a
firstRightOrLefts = runExcept . msum . fmap (withExcept (:[]) . except)
于 2014-11-05T20:12:58.970 回答