25

在我的应用程序的某个地方,我收到了Either ParserError MyParseResult来自 Parsec 的消息。在下游,此结果通过使用其他库完成了一些其他解析。在解析的第二阶段,也可能会发生某种错误,我想将其作为 a 传递Left String,但为此我需要将结果从 Parsec 转换为String。为了实现这一点,我需要一个允许我使用函数映射 aLeftshow函数。

我正在考虑的映射函数看起来像这样:

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

但我很惊讶没有在 hackage db 上找到任何匹配的东西。所以现在我怀疑我是否使用了正确的方法来解决我的问题。

为什么标准库中没有这样的功能?我的方法有什么问题?

4

4 回答 4

36

我们在标准库中有这样的功能,

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

是对任意箭头的推广。替换(->)a应用它的中缀,以获得专业化

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

原则上您的方法没有错,这是处理这种情况的明智方法。

于 2012-11-22T00:02:54.050 回答
21

另一种选择是Bifunctor使用Either. 然后你有

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

(也Bifunctor可以用来遍历第一部分(a,b)。)

于 2012-11-22T08:11:33.253 回答
14

这可以通过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
于 2012-11-22T05:45:54.313 回答
4

另一个简单的选择mapLeftData.Either.Combinators

mapLeft :: (a -> c) -> Either a b -> Either c b
于 2018-06-07T17:54:59.793 回答