scala 具有结果累加的Maybe函子

ttisahbt  于 5个月前  发布在  Scala
关注(0)|答案(1)|浏览(52)

我想为Option实现一个类似于functor的东西,它可以累积成功的结果。
它的行为应该像这样(类似于下面的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)

字符串
我知道这不是一个合适的函子,因为它不保持同一性:
Some(42).map(identity) # => Some[(Int, Int]) = Some((42, 42))
为了添加一些上下文,我认为当有一个Map链时会很有用:

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 => ...
}


因此,我正在寻找一个众所周知的解决方案/方法/理论术语,与期望的行为有关

deyfvvtc

deyfvvtc1#

你可以用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]]

  • 在这两种情况下,如果操作返回Option,我都没有管理flatMap情况,但这可以相对容易地由读者实现。

相关问题