【问题标题】:Mapping over Either's Left映射到 Either 的左侧
【发布时间】:2012-11-21 23:54:52
【问题描述】:

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

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

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

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

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

【问题讨论】:

  • 不能使用mapLeft _ x = x,必须是mapLeft _ (Right x) = Right x,参数和结果类型不同。

标签: haskell either


【解决方案1】:

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

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

是对任意箭头的概括。将(->) 替换为a 并应用它的中缀,以获得专业化

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

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

【讨论】:

  • 哦。我并不感到惊讶,我什至没有怀疑它是我需要的。我还没准备好将箭头视为一种类型)感谢您睁开眼睛!
  • lens 也提供此功能,名称为over traverseLeft
  • 在最近的版本中是over _left——以防以后有人遇到这个问题。
【解决方案2】:

另一种选择是使用BifunctorEither 实例。然后你有

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

【讨论】:

  • 在 2012 年是 _Left_Right 用小写的 lr 拼写吗?
  • 根据目前的文档,他们是_Left_Right
【解决方案4】:

另一个简单的选项是mapLeft in Data.Either.Combinators:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-08
    • 2023-04-03
    • 2021-12-18
    • 1970-01-01
    • 2020-03-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多