我可能在文档中遗漏了一些正确的内容,但我真的无法理解它 - 我一直在通过反复试验来教自己Scala。
鉴于功能f: A => C
,执行以下转换的惯用方式是什么?
Either[A, B] -> Either[C, B]
Either[B, A] -> Either[B, C]
(如果我有两个这样的功能并希望转换双方,我可以一次完成所有操作还是应该依次应用两次成语?)
Option[A] -> Option[C]
(我觉得这应该以某种方式使用for (...) yield
;我可能只是在对它进行消隐,当我看到答案时会感到愚蠢)
完全是Either
的“投影”,无论如何?
答案 0 :(得分:18)
你做了:
either.left.map(f)
或a:
either.right.map(f)
您还可以使用for-comprehension:for (x <- either.left) yield f(x)
以下是在map
上执行Either[Boolean, Int]
的更具体示例:
scala> val either: Either[Boolean, Int] = Right(5)
either: Either[Boolean, Int] = Right(5)
scala> val e2 = either.right.map(_ > 0)
either: Either[Boolean, Boolean] = Right(true)
scala> e2.left.map(!_)
either: Either[Boolean, Boolean] = Right(true)
编辑:
它是如何工作的?假设你有Either[A, B]
。调用left
或right
会创建一个LeftProjection
或RightProjection
对象,该对象是包含Either[A, B]
对象的包装器。
对于left
包装器,应用具有函数map
的后续f: A => C
来将Either[A, B]
转换为Either[C, B]
。它通过在引擎盖下使用模式匹配来检查Either
实际上是Left
。如果是,则会创建新的Left[C, B]
。如果没有,只需更改即可创建具有相同基础值的新Right[C, B]
。
反之亦然right
包装器。实际上,说either.right.map(f)
表示 - 如果任一(Either[A, B]
)对象包含Right
值,则映射它。否则,保持原样,但更改任一对象的类型B
,就像您已映射它一样。
从技术上讲,这些预测仅仅是包装纸。从语义上讲,它们是一种表示您正在做的事情,假设存储在Either
对象中的值是Left
或Right
。如果这个假设是错误的,那么映射什么都不做,但类型参数会相应地改变。
答案 1 :(得分:3)
鉴于f: A=>B
和xOpt: Option[A]
,xOpt map f
会产生您需要的Option[B]
。
鉴于f: A=>B
和xOrY: Either[A, C]
,xOrY.left.map(f)
生成您正在寻找的Either
,只映射第一个组件;同样,您可以处理RightProjection
的{{1}}。
如果您有两个功能,则可以为两个组件Either
定义映射。
答案 2 :(得分:0)
val e1:Either[String, Long] = Right(1)
val e2:Either[Int,Boolean] = e1.left.map(_.size).right.map( _ >1 )
// e2: Either[Int,Boolean] = Right(false)