Возьмите первые права из списка в Haskell

Во-первых, у меня есть (бесконечный) список Eithers, который получается так:

x :: A
...

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

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

Список будет содержать несколько Rights (всегда конечное число), а затем то же самое Left значение повторяется. Что мне нужно, это взять все Rightс и один Left после них. В этом конкретном случае это можно сделать, например, изменив функцию, но меня также интересует лучший общий метод.

3 ответа

Решение

Позвольте мне предложить более инвазивные изменения. Вместо

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 а также 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

(Почему нет isRight а также isLeft определяется в Data.Either?)

Другие вопросы по тегам