scala - 延迟遍历首次成功时短路的函数集合

标签 scala scala-cats

目标是延迟评估停止并返回第一个满意结果的函数集合。计算应该是顺序的。这是我的尝试

def f1(i: Int): Either[String, Int] = {println(s"f1($i)"); Left("boom-f1") }
def f2(i: Int): Either[String, Int] = {println(s"f2($i)"); Left("boom-f2") }
def f3(i: Int): Either[String, Int] = {println(s"f3($i)"); Right(i) }

val in = 42

(f1(in) #:: f2(in) #:: f3(in) #:: Stream.empty) collectFirst { case Right(x) => x } toRight("boom")

输出

f1(42)
f2(42)
f3(42)
res0: Either[String,Int] = Right(42)

我们看到所有三个都被处决,同时

def f1(i: Int): Either[String, Int] = {println(s"f1($i)"); Right(i) }
def f2(i: Int): Either[String, Int] = {println(s"f2($i)"); Right(i) }
def f3(i: Int): Either[String, Int] = {println(s"f3($i)"); Right(i) }

会输出

f1(42)
res0: Either[String,Int] = Right(42)

我们只看到一个被处决的地方。

猫是否为这种懒惰的失败偏向遍历提供抽象?

最佳答案

您可以使用Ior数据类型是两种数据类型之间的包含或关系。

import cats.data.Ior
import cats.implicits._

import scala.annotation.tailrec

object Main2 {
  def main(args: Array[String]) : Unit = {
    def f1(i: Int): Either[String, Int] = {println(s"f1($i)"); Left("boom-f1") }
    def f2(i: Int): Either[String, Int] = {println(s"f2($i)"); Left("boom-f2") }
    def f3(i: Int): Either[String, Int] = {println(s"f3($i)"); Right(i) }

    def traverseLazy(input: Int, list: List[Int => Either[String, Int]]): Ior[List[String], Int] = {
      @tailrec
      def go(ls: List[Int => Either[String, Int]], acc: List[String]): Ior[List[String], Int] = ls match {
        case x :: xs => x(input) match  {
          case Left(error) => go(xs, error :: acc)
          case Right(value) => if (ls.isEmpty) value.rightIor else Ior.both(acc, value)
        }
        case Nil => acc.leftIor
      }

      go(list, List.empty)
    }

    val res = traverseLazy(42, List(f1, f2, f3)).fold(
      _.intercalate("\n"),
      res => s"succeeded with $res",
      (errors, res) => s"completed successfully with res $res but some errors were also found: ${errors.intercalate(", ")}")

    println(res)
  }
}

关于scala - 延迟遍历首次成功时短路的函数集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58035836/

相关文章:

Scala:在读者内部使用防护进行理解

java - Riak Java Client 注释在 Scala 案例类中无法识别?

scala - 路径依赖类型 : Idris to Scala

scala - cats-effect:如何获得隐式的 NonEmptyParallel

Scala Cat 库验证列表按错误代码分组

scala - 在函数参数级别实现 Ad hoc 多态性(混合不同类型的参数)

scala - 使用 Unapply 提取相同的类型类

scala - 抽象 val 而不是主构造函数参数

scala - scala 2.11 中弃用的 `scala.collection.script` 的替代方案?

scala - 将 HList 中的验证应用于案例类