Question

Firstly, I have a (infinite) list of Eithers, which is produced like this:

x :: A
...

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

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

The list will contain several Rights (always a finite number) and then the same Left value repeated. What I need is to take all the Rights and one Left after them. In this particular case it can be done also by changing the function for example, but I'm also interested in best general method.

Was it helpful?

Solution

Let me suggest a more invasive change. Instead of

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

consider

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

and forget xs entirely. Where before f was a single step of the iteration, it is now recursive; where before it would return Right a, you now tell [a] >> f a; where before it would return Left b, you now return b.

If it's really necessary, you can still access the individual pieces of the Writer, namely the [A] and B, via execWriter and evalWriter (or by using runWriter to access them both at once):

xs :: [A]
b :: B
(xs, b) = runWriter (f x)

OTHER TIPS

You could use span to split the list between the Right elements and the Left ones, then pattern match to grab the first Left.

(rights, firstLeft : _) = span isRight xs
    where isRight (Right _) = True
          isRight _         = False

I'd do it like this, if you need to keep them all in the same list:

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

(Why aren't isRight and isLeft defined in Data.Either?)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top