ms-*_*-tg 6 functional-programming scala
使用Scala 2.9.1,考虑以下两个实例Either:
scala> val er: Either[String, Int] = Right(1)
er: Either[String,Int] = Right(1)
scala> val el: Either[String, Int] = Left("a")
el: Either[String,Int] = Left(a)
Run Code Online (Sandbox Code Playgroud)
很棒的是,通过使用left和right投影,人们可以使用for-comprehension(通过投射Either的偏向monad):
scala> for { r <- er.right } yield r * 2
res6: Product with Either[String,Int] with Serializable = Right(2)
scala> for { r <- el.right } yield r * 2
res7: Product with Either[String,Int] with Serializable = Left(a)
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释为什么决定不让filter方法返回Either?我希望以下工作:
scala> for { r <- er.right if r > 2 } yield r * 2 // r is NOT greater than 2!
res8: Product with Either[String,Int] with Serializable = Left(a)
Run Code Online (Sandbox Code Playgroud)
相反,您会收到以下错误:: 9:错误:值*不是{r < - er.right的[Nothing,Int]的成员,如果r> 2},则产生r*2
看来底层调用Either.RightProjection#filter实际上返回一个Option:
scala> er.right.filter(_ > 2)
res9: Option[Either[Nothing,Int]] = None
Run Code Online (Sandbox Code Playgroud)
这使得在for-comprehension中使用if子句失败了,至少我尝试使用它的方式.
有没有人解释为什么这种设计是这样的?
Ben*_*mes 12
它归结为这样一个事实:如果你有一个Right(b),但你的过滤谓词失败了,你就没有价值Left.
您可以想象一个适用于您的情况的实现Either[String, Int],通过使用默认值失败Left("").Scala标准库没有为您生成值的功能,因为它不包含诸如monoid之类的概念,它将确定类型的"空"值.
Scalaz库确实包含一个monoid类型类,而且版本7还包括一个右偏的析取类型,\/[A, B](同构Either[A, B]),filter如果左类型是一个monoid ,它有一个方法:
scala> \/.right[String, Int](1).filter(_ > 2)
res1: scalaz.\/[String,Int] = -\/()
Run Code Online (Sandbox Code Playgroud)
但是对于一般情况你不能这样做 - 如果你有Either[Nothing, Int],你永远不会产生左值.
| 归档时间: |
|
| 查看次数: |
1170 次 |
| 最近记录: |