scala - 有权访问 Option 容器的 Option operators

标签 scala

我有一些函数 (f2..fn) 接受 A,并返回 Option[A]。这非常有效(假设 f1:X => Option[A])来做例如

f1(x) flatMap f2 flatMap f3

现在我希望能够记录发生的事情,尤其是在引入 None 的地方。我希望能够插入一个函数,例如:

log_none(m:String):Option[A] => Option[A] 

如果遇到 None,它会产生日志记录的副作用。

似乎没有任何选项功能适用于此(在阅读例如 tonymorris.github.io/blog/posts/scalaoption-cheat-sheet/之后)

理想情况下,它看起来像这样:

f1(x) <.> log_none("f1 failed") flatMap f2 <.> log_none("f2 failed") ...

我无法立即看到一种优雅、惯用的方式来做到这一点——我看不到任何东西可以放在 <.> 位置。

最佳答案

这是 scalaz 验证的一个很好的案例。它与 Option 类似,但它不是 None,而是给你一个错误值。

之前:

def f1(x: Int): Option[Int]
def f2(x: Int): Option[Int]
def f2(x: Int): Option[Int]

for {
  x1 <- f1(x)
  x2 <- f2(x1)
  x3 <- f3(x2)
} yield x3

您可以使用 toSuccess 隐式进行简单的转换

import scalaz.{Validation, Success, Failure}
import scalaz.Validation.FlatMap._
import scalaz.syntax.std.option._

def oldf1(x: Int): Option[Int]

def f1(x: Int): Validation[String, Int] = oldf1(x).toSuccess("f1 failed")
def f2(x: Int): Validation[String, Int]
def f2(x: Int): Validation[String, Int]

val validatedX3: Validation[String, Int] = for {
  x1 <- f1(x)
  x2 <- f2(x1)
  x3 <- f3(x2)
} yield x3

validatedX3 match {
  case Success(i) =>
    Some(i)
  case Failure(errStr) => 
    log(errStr)
    None
}

或者交替

validatedX3.leftMap(log).toOption

你可以用 scala Either 做类似的事情,但它更痛苦,因为你需要在所有地方使用 .toRightProjection

我假装 Validation 是 monadic 与 Validation.FlatMap 导入即使它不是,但如果你的 f1,2,3 不这样做,你也可以使用应用版本来收集多个错误需要测序。 http://eed3si9n.com/learning-scalaz/Validation.html

关于scala - 有权访问 Option 容器的 Option operators,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27319039/

相关文章:

swing - Scala-Swing 中的 MVP

scala - 如何在没有 SQL 查询的情况下使用 Spark Dataframe 检查相等性?

scala - 从 Scala Breeze 中的文件中读取矩阵

scala - 在调用 main 方法之前,Scala 静态值初始化似乎没有发生

mysql - 带有 Hikari 设置的 Doobie

Scala : Futures with map, flatMap 用于 IO/CPU 密集型任务

scala - 匹配可能不是详尽的警告是不正确的

list - 如何在 Scala 的列表列表中求和/合并每个值

scala - Windows 上的 jpackage : The system cannot find file, 错误 103

scala - 是否可以在 Scala 中装饰方法?