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

Kar*_*tel 10 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呢?

axe*_*l22 18

你做了一个:

either.left.map(f)
Run Code Online (Sandbox Code Playgroud)

或者:

either.right.map(f)
Run Code Online (Sandbox Code Playgroud)

你也可以使用for-understanding: for (x <- either.left) yield f(x)

这里是做的更具体的例子mapEither[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)
Run Code Online (Sandbox Code Playgroud)

编辑:

它是如何工作的?说你有Either[A, B].调用leftright创建一个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.如果此假设错误,则映射不执行任何操作,但类型参数会相应更改.