Сопоставление либо слева

Где-то в моем приложении я получаю Either ParserError MyParseResult от Parsec. В результате этого результата выполняется другой анализ, использующий другие библиотеки. Во время этой второй фазы синтаксического анализа также может возникнуть некоторая ошибка, которую я хотел бы передать как Left String, но для этого мне также нужно преобразовать результат из Parsec в String. Чтобы достичь этого, мне нужна функция, которая позволит мне отобразить через Left с помощью функции show.

Функция отображения, о которой я думаю, выглядит примерно так:

mapLeft :: (a -> b) -> Either a c -> Either b c
mapLeft f (Left x) = Left $ f x
mapLeft _ x = x

Но я был очень удивлен, не найдя ничего подходящего для hackage db. Итак, теперь у меня возникают сомнения в том, что я использую правильный подход к моей проблеме.

Почему в стандартной библиотеке нет такой функции? Что не так с моим подходом?

Ответы

Ответ 1

У нас есть такая функция в стандартных библиотеках,

Control.Arrow.left :: a b c -> a (Either b d) (Either c d)

- обобщение на произвольные стрелки. Замените (->) на a и примените его infix, чтобы получить специализацию

left :: (b -> c) -> Either b d -> Either c d

Нет ничего плохого в вашем подходе в принципе, это разумный способ справиться с ситуацией.

Ответ 2

Другой вариант - использовать экземпляр Bifunctor для Either. Тогда у вас есть

first :: (a -> b) -> Either a c -> Either b c

(Также Bifunctor может быть использован для перемещения по первой части (a,b).)

Ответ 3

Это можно легко сделать с помощью lens:

import Control.Lens

over _Left (+1) $ Left 10   => Left 11
over _Left (+1) $ Right 10  => Right 10
over _Right (+1) $ Right 10 => Right 11

Ответ 4

Другой простой вариант - mapLeft в Data.Either.Combinators:

mapLeft :: (a -> c) -> Either a b -> Either c b