用Haskell写右首还是左首的惯用方法?
我有以下方法:用Haskell写右首还是左首的惯用方法?,haskell,either,Haskell,Either,我有以下方法: firstRightOrLefts :: [Either b a] -> Either [b] a firstRightOrLefts eithers = case partitionEithers eithers of (_, (x : _)) -> Right x (xs, _) -> Left xs 让我烦恼的是丑陋的模式匹配,我想知道是否有更惯用的方法来编写这个方法。我的想法是,我有一系列的计算可以返回它们
firstRightOrLefts :: [Either b a] -> Either [b] a
firstRightOrLefts eithers =
case partitionEithers eithers of
(_, (x : _)) -> Right x
(xs, _) -> Left xs
让我烦恼的是丑陋的模式匹配,我想知道是否有更惯用的方法来编写这个方法。我的想法是,我有一系列的计算可以返回它们,我只想得到第一个结果或所有的错误消息。也许我用错了数据结构。也许作者monad更适合这个任务。在这一点上我真的不确定。为任何帮助干杯 的
MonadPlus
实例具有以下行为:
import Control.Monad
import Control.Monad.Trans.Except
firstRightOrLefts :: [Either e a] -> Either [e] a
firstRightOrLefts = runExcept . msum . fmap (withExcept (:[]) . except)
反向约定实际上只是
或的单子定义,而序列的定义就足以满足这一点:
ghci> :t sequence :: [Either a b] -> Either a [b]
sequence :: [Either a b] -> Either a [b]
:: [Either a b] -> Either a [b]
因此,要将此应用到您的案例中,我们需要一个函数:
firstRightOrLefts = fe . sequence . map fe
where fe (Left a) = Right a
fe (Right b) = Left b
这实际上是一个很好的答案,简单明了。让它再开放一天,以防有更简单的答案,否则我会接受这个答案。我的意思是,你也可以写你的作为firstright或lefts=go[]where go acc e=case of[]->Left(reverse acc);(右r):es->右r;(左l):es->go(左:acc)es
(如果需要)。我真正喜欢上述答案的是,它揭示了您可能正在以一种与人们通常的方式相反的方式使用任意一个monad(至少在这个操作中):因为您希望积累错误并在第一次成功时停止,所以与希望在第一次错误时停止的人相比,您的用例被翻转了。这可能无关紧要,但如果您正在编写解析器,那么了解这一点很有用!您还可以编写fe=左右任意一个。这非常好。尤其是因为它使用标准的操作员来完成这项工作。我将进一步了解这些类型,看看它是如何做的。