我想为
Option
实现类似仿函数的东西,它可以积累成功的结果。
它的行为应该像这样(下面类似 scala 的代码):
Some(1).map(_ + 1) # => Some[(Int, Int)] = Some((1,2))
Some(1).map(_ + 1).map(_ * 3) # => Some[(Int, Int, Int)] = Some((1,2,6))
Some(1).map(_ => None) # Option[None.type] = Some(None)
我do理解这不是一个合适的函子,因为它不保留身份:
Some(42).map(identity) # => Some[(Int, Int]) = Some((42, 42))
为了添加一些上下文,我认为当存在一系列地图时它会很有用:
val result = Some(42).map(compute_second_value).map(compute_third_value)
以及结果的模式匹配不仅取决于
result
最终值:
result match {
case Some(value) => do_something_with_all_results(result._1, result._2, result._3)
case None => ...
}
所以我正在寻找与所需行为相关的众所周知的解决方案/方法/理论术语
您可以使用 Scala 中的
foldLeft
以“通用”方式实现它,并处理序列而不是元组:
val ops: Seq[Int => Int] = Seq(computeSecondValue, computeThirdValue)
ops.foldLeft(Seq(1)) { case (acc, op) =>
acc :+ op(acc.last)
}
// Seq[Int]
// Seq(1, computeSecondValue(1), computeThirdValue(computeSecondValue(1)))
或者采用不太通用的方法并保留元组:
for {
first <- Some(1)
second = computeSecondValue(first)
third = computeThirdValue(second)
} yield (first, second, third)
// Option[Tuple3[Int, Int, Int]]
在这两种情况下,如果操作返回
flatMap
,我都没有管理 Option
情况,但这可以由读者相对轻松地实现。