是否有一个函数可以分别采用两个转换函数来转换/映射Either 的Left 和Right 情况?

Shr*_* Ye 2 monads haskell scala either

我还没有在 Scala 或 Haskell 中找到一个函数可以同时转换/映射Either'sLeftRightcase 两个转换函数,即类型为

(A => C, B => D) => Either[C, D]
Run Code Online (Sandbox Code Playgroud)

forEither[A, B]在 Scala 中,或类型

(a -> c, b -> d) -> Either a b -> Either c d
Run Code Online (Sandbox Code Playgroud)

在哈斯克尔。在 Scala 中,它相当于这样调用fold

(A => C, B => D) => Either[C, D]
Run Code Online (Sandbox Code Playgroud)

或者在 Haskell 中,它相当于这样调用either

mapLeftOrRight :: (a -> c) -> (b -> d) -> Either a b -> Either c d
mapLeftOrRight fa fb = either (Left . fa) (Right . fb)
Run Code Online (Sandbox Code Playgroud)

库中是否存在这样的功能?如果没有,我觉得这样的东西很实用,为什么语言设计者选择不放在那里?

lef*_*out 7

不了解 Scala,但 Haskell 有一个类型签名搜索引擎。它没有给出你写的结果,但这只是因为你采用了一个元组参数,而 Haskell 函数按照惯例是柯里化https://hoogle.haskell.org/?hoogle=(a -> c) -> (b -> d) -> Either a b -> Either c d确实提供匹配,最明显的是:

mapBoth :: (a -> c) -> (b -> d) -> Either a b -> Either c d
Run Code Online (Sandbox Code Playgroud)

...实际上,即使是 Google 也发现了这一点,因为类型变量恰好与您想象的一样。(如果你写它,(x -> y) -> (p -> q) -> Either x p -> Either y q Hoogle 也会找到。)

但实际上,正如 Martijn 所说,这种行为 forEither只是bifunctor的一个特例,实际上 Hoogle 还为您提供了更通用的形式,该形式在base库中定义:

bimap :: Bifunctor p => (a -> b) -> (c -> d) -> p a c -> p b d
Run Code Online (Sandbox Code Playgroud)

TBH 我有点失望的是,Hoogle 本身并没有想出咖喱签名或交换参数。很确定它实际上曾经自动执行此操作,但在某些时候他们简化了算法,因为由于库数量庞大,所花费的时间和结果数量都失控了。

  • 我相信曾经有人正在为 Scala 开发一个与 Hoogle 相当的东西,使用 scaladoc 和 Scala-meta 作为基础,但我认为它没有任何进展。我的方法是使用 Hoogle 查找名称,然后在 Scalaz 和 Cats 中搜索该名称,假设它们会使用相同的名称。 (4认同)

Mar*_*lic 5

Cats 提供Bifunctor,例如

import cats.implicits._

val e: Either[String, Int] = Right(41)
e.bimap(e => s"boom: $e", v => 1 + v)
// res0: Either[String,Int] = Right(42)
Run Code Online (Sandbox Code Playgroud)

  • 通过名称“bimap”,我可以找到[Scala Contributors 上的一篇文章建议添加此内容](https://contributors.scala-lang.org/t/add-bimap-method-to-either/3074)。 (2认同)