Shr*_* Ye 2 monads haskell scala either
我还没有在 Scala 或 Haskell 中找到一个函数可以同时转换/映射Either'sLeft和Rightcase 两个转换函数,即类型为
(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)
库中是否存在这样的功能?如果没有,我觉得这样的东西很实用,为什么语言设计者选择不放在那里?
不了解 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 dRun 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 dRun Code Online (Sandbox Code Playgroud)
† TBH 我有点失望的是,Hoogle 本身并没有想出咖喱签名或交换参数。很确定它实际上曾经自动执行此操作,但在某些时候他们简化了算法,因为由于库数量庞大,所花费的时间和结果数量都失控了。
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)