3

首先,我有一个(无限的)Eithers 列表,它的生成方式如下:

x :: A
...

f :: A -> Either B A
...

xs :: [Either B A]
xs = iterate (>>=f) (Right x)

该列表将包含几个Rights (总是一个有限的数字),然后Left重复相同的值。我需要的是把所有的Rights 和一个Left在他们之后。在这种特殊情况下,例如也可以通过更改函数来完成,但我也对最佳通用方法感兴趣。

4

3 回答 3

9

让我提出一个更具侵略性的改变。代替

x :: A
f :: A -> Either B A
xs :: [Either B A]

考虑

x :: A
f :: A -> Writer [A] B

并完全忘记xs。以前f是单步迭代,现在是递归的;以前它会回来的地方Right a,你现在tell [a] >> f a;以前它会回来的地方Left b,你现在return b

如果确实有必要,您仍然可以访问 的各个部分Writer,即[A]and B,通过execWriterand evalWriter(或使用runWriter同时访问它们):

xs :: [A]
b :: B
(xs, b) = runWriter (f x)
于 2012-10-16T20:22:48.290 回答
5

您可以使用在元素和元素span之间拆分列表,然后进行模式匹配以获取第一个.RightLeftLeft

(rights, firstLeft : _) = span isRight xs
    where isRight (Right _) = True
          isRight _         = False
于 2012-10-16T18:39:38.183 回答
1

如果您需要将它们全部保存在同一个列表中,我会这样做:

answer = map fst . takeWhile snd $ zip xs (True : map isRight xs)
  where isRight (Right _) = True
        isRight _         = False

(为什么不在Data.Either中定义isRight和定义?)isLeft

于 2012-10-16T19:30:33.950 回答