首先,我有一个(无限的)Either
s 列表,它的生成方式如下:
x :: A
...
f :: A -> Either B A
...
xs :: [Either B A]
xs = iterate (>>=f) (Right x)
该列表将包含几个Right
s (总是一个有限的数字),然后Left
重复相同的值。我需要的是把所有的Right
s 和一个Left
在他们之后。在这种特殊情况下,例如也可以通过更改函数来完成,但我也对最佳通用方法感兴趣。
让我提出一个更具侵略性的改变。代替
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
,通过execWriter
and evalWriter
(或使用runWriter
同时访问它们):
xs :: [A]
b :: B
(xs, b) = runWriter (f x)
您可以使用在元素和元素span
之间拆分列表,然后进行模式匹配以获取第一个.Right
Left
Left
(rights, firstLeft : _) = span isRight xs
where isRight (Right _) = True
isRight _ = False
如果您需要将它们全部保存在同一个列表中,我会这样做:
answer = map fst . takeWhile snd $ zip xs (True : map isRight xs)
where isRight (Right _) = True
isRight _ = False
(为什么不在Data.Either中定义isRight
和定义?)isLeft