处理选项和任何一种类型 - 惯用转换?

时间:2011-09-21 21:09:03

标签: scala idioms

我可能在文档中遗漏了一些正确的内容,但我真的无法理解它 - 我一直在通过反复试验来教自己Scala。

鉴于功能f: A => C,执行以下转换的惯用方式是什么?

Either[A, B] -> Either[C, B]

Either[B, A] -> Either[B, C]

(如果我有两个这样的功能并希望转换双方,我可以一次完成所有操作还是应该依次应用两次成语?)

Option[A] -> Option[C]

(我觉得这应该以某种方式使用for (...) yield;我可能只是在对它进行消隐,当我看到答案时会感到愚蠢)

完全Either的“投影”,无论如何?

3 个答案:

答案 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]。调用leftright会创建一个LeftProjectionRightProjection对象,该对象是包含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对象中的值是LeftRight。如果这个假设是错误的,那么映射什么都不做,但类型参数会相应地改变。

答案 1 :(得分:3)

鉴于f: A=>BxOpt: Option[A]xOpt map f会产生您需要的Option[B]

鉴于f: A=>BxOrY: 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)