Возьмите первые права из списка в Haskell
Во-первых, у меня есть (бесконечный) список Either
s, который получается так:
x :: A
...
f :: A -> Either B A
...
xs :: [Either B A]
xs = iterate (>>=f) (Right x)
Список будет содержать несколько Right
s (всегда конечное число), а затем то же самое 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?)