scalaz Disjunction中的安全链接

时间:2016-08-16 22:09:50

标签: scala functional-programming scalaz

我试图围绕scalaz分离(\ /),但它还没有点击。请考虑以下事项:

scala> import scalaz._
import scalaz._

scala> def danger(i: Int): Int = throw new Exception("boom")
danger: (i: Int)Int

scala> \/-(1).map(danger)
java.lang.Exception: boom
  at .danger(<console>:10)
  at $anonfun$1.apply(<console>:12)
  at $anonfun$1.apply(<console>:12)
  at scalaz.$bslash$div.map(Either.scala:111)
  ... 43 elided

我天真的期望是,因为我在danger内调用\/.map,所以最后一个语句应该返回-\/(Exception("boom")),而不是炸毁。

我可以用

修复它
scala> \/-(1).flatMap(i => \/.fromTryCatchNonFatal(danger(i)))
res4: scalaz.\/[Throwable,Int] = -\/(java.lang.Exception: boom)

但这会变得非常冗长和失控。是否有一种更简单的方法可以安全地链接带有析象的变换?

1 个答案:

答案 0 :(得分:1)

理想情况下,danger应该返回\/[A, B]。如果您无法修改danger的返回类型,请创建一个版本dangerousFn。这将使您能够以功能方式进行flatMap。 编辑:重新阅读OP的解决方案后,我正在使用fromTryCatchNonFatal功能

import scalaz._

def danger(i: Int): Int = throw new Exception("boom")
val dangerousFn = (danger _).andThen(\/.fromTryCatchNonFatal)

for {
  num <- \/-(1)
  value <- dangerousFn(num)
} yield {
  "This will never be reached"
}

输出:

import scalaz._

danger: danger[](val i: Int) => Int

res0: scalaz.\/[Throwable,String] = -\/(java.lang.Exception: boom)