首先,我有一个{无限的} Either
s列表,它是这样产生的:
x :: A
...
f :: A -> Either B A
...
xs :: [Either B A]
xs = iterate (>>=f) (Right x)
该列表将包含多个Right
s(始终为有限数字),然后重复相同的Left
值。我需要的是在它们之后取所有Right
和一个Left
。在这种特殊情况下,也可以通过更改函数来完成,但我也对最佳通用方法感兴趣。
答案 0 :(得分: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]
的各个部分,即B
和execWriter
1}}(或使用evalWriter
一次访问它们):
runWriter
答案 1 :(得分:5)
您可以使用span
在Right
元素和Left
元素之间拆分列表,然后模式匹配以抓住第一个Left
。
(rights, firstLeft : _) = span isRight xs
where isRight (Right _) = True
isRight _ = False
答案 2 :(得分:1)
如果你需要将它们全部保存在同一个列表中,我会这样做:
answer = map fst . takeWhile snd $ zip xs (True : map isRight xs)
where isRight (Right _) = True
isRight _ = False
(为什么Data.Either中没有定义isRight
和isLeft
?)