在 EitherT 和 Validation 之间切换以累积误差或遍历

2024-02-25

假设我有以下功能:

def getRemoteThingy(id: Id): EitherT[Future, NonEmptyList[Error], Thingy]

Given a List[Id],我可以轻松地检索List[Thingy]通过使用Traverse[List]:

val thingies: EitherT[Future, NonEmptyList[Error], List[Thingy]] = 
  ids.traverseU(getRemoteThingy)

它将使用Applicative实例为EitherT这将基于flatMap所以我只会得到第一个NonEmptyList[Error],它不会附加所有这些。那是对的吗?

现在,如果我真的想累积错误,我可以在EitherT and Validation。例如:

def thingies2: EitherT[Future, NonEmptyList[Error], List[Thingy]] = 
  EitherT(ids.traverseU(id => getRemoteThingy(id).validation).map(_.sequenceU.disjunction))

它有效,我最后得到了所有错误,但这非常麻烦。我可以做到simpler通过使用Applicative作品:

type ValidationNelError[A] = Validation[NonEmptyList[Error], A]
type FutureValidationNelError[A] = Future[ValidationNelError[A]]
implicit val App: Applicative[FutureValidationNelError] =
  Applicative[Future].compose[ValidationNelError]

def thingies3: EitherT[Future, NonEmptyList[Error], List[Thingy]] = 
  EitherT(
    ids.traverse[FutureValidationNelError, Thingy](id => 
      getRemoteThingy(id).validation
    ).map(_.disjunction)
  )

比其他的更长,但所有的管道都可以轻松地在代码库中共享。

您认为我的解决方案怎么样?有没有更优雅的方法来解决这个问题?你通常如何应对?

非常感谢。

EDIT:

我有一种疯狂的解决方案,使用自然变换来拉皮条Traversable。您显然需要类型别名才能工作,这就是我重新定义的原因getRemoteThingy:

type FutureEitherNelError[A] = EitherT[Future, NonEmptyList[String], A]

def getRemoteThingy2(id: Id): FutureEitherNelError[Thingy] = getRemoteThingy(id)

implicit val EitherTToValidation = new NaturalTransformation[FutureEitherNelError, FutureValidationNelError] {
  def apply[A](eitherT: FutureEitherNelError[A]): FutureValidationNelError[A] = eitherT.validation
}

implicit val ValidationToEitherT = new NaturalTransformation[FutureValidationNelError, FutureEitherNelError] {
  def apply[A](validation: FutureValidationNelError[A]): FutureEitherNelError[A] = EitherT(validation.map(_.disjunction))
}

implicit class RichTraverse[F[_], A](fa: F[A]) {
  def traverseUsing[H[_]]: TraverseUsing[F, H, A] = TraverseUsing(fa)
}

case class TraverseUsing[F[_], H[_], A](fa: F[A]) {
  def apply[G[_], B](f: A => G[B])(implicit GtoH: G ~> H, HtoG: H ~> G, A: Applicative[H], T: Traverse[F]): G[F[B]] =
    HtoG(fa.traverse(a => GtoH(f(a))))
}

def thingies4: FutureEitherNelError[List[Thingy]] = 
  ids.traverseUsing[FutureValidationNelError](getRemoteThingy2)

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 EitherT 和 Validation 之间切换以累积误差或遍历 的相关文章

  • 写入 Delta 表时检测到架构不匹配 - Azure Databricks

    我尝试将 small radio json json 加载到 Delta Lake 表 在此代码之后我将创建表 我尝试创建 Delta 表 但收到错误 写入 Delta 表时检测到架构不匹配 可能与分区有关events write form
  • Scala 2.10、Double.isNaN 和拳击

    在 Scala 2 10 中 是someDouble isNaN预计装箱 运行我的代码调用 isNaN通过反编译器 我仍然看到对double2Double在我的代码中 鉴于新的AnyVal在 2 10 中工作 我希望它不会比java lan
  • scala sbt 在多项目上测试运行设置和清理命令一次

    我知道我可以通过修改 testOptions 在 sbt 中添加设置和清理代码以用于测试阶段 例如 val embedMongoTestSettings Seq Setting Seq testOptions in Test Tests S
  • 不使用 CPU 时 Cassandra 超时

    我使用 Phantom DSL 和 Datastax Cassandra 驱动程序时遇到 Cassandra 超时 然而 Cassandra 似乎并没有超载 以下是我得到的异常 com datastax driver core except
  • Scala 重载构造函数和 super

    我无法理解如何在 Java 上开发类似于以下的 Scala 代码 public abstract class A protected A protected A int a public abstract class B protected
  • 《使用 Apache Flink 进行流处理》如何从 IntelliJ 运行书籍代码?

    如中所述这个帖子 https stackoverflow com questions 61043860 how to run first example of apache flink我无法成功运行 使用 Apache Flink 进行流处
  • Scala:如何编写将类型化为接收者的实现类型的对象返回的方法

    我知道 Scala 中不推荐使用案例类继承 但为了简单起见 我在以下示例中使用了它 scala gt case class Foo val f String def foo g String Foo this copy f g define
  • 自定义 NIO 文件系统无法通过 SBT 的测试任务加载

    为了进行测试 我使用内存中的 NIOFileSystem执行 memoryfs https github com openCage memoryfs 我以前已经利用过它 并且它似乎运行良好 例如梅文 然而 现在 在SBT项目中 不可能初始化
  • 新式(“内联”)宏需要 scala.meta

    我刚刚更新到 scala meta 2 0 0 M1 和最新的 scala 2 12 3 现在宏不再编译 我所做的唯一更改是将元版本从 1 8 0 更改为 2 0 0 M1 错误 新式 内联 宏需要 scala meta 有谁知道是否有快速
  • 对于空列表,max() 应该返回什么?

    Got java util NoSuchElementException head of empty list所以我试着检查一下 但现在我明白了 info max of a few numbers FAILED info 0 did not
  • Scala 集合不一致

    为什么 Scala Collections API 中的集合和列表之间缺乏一致性 例如 有不可变的 Set 但也有可变的 Set 如果我想使用后者 我可以简单地这样做 val set Set A set new A 但是 本身不存在可变列表
  • 最小重复子串

    我正在看 Perl代码高尔夫页面 http www perlmonks org node id 82878 不要问为什么 并遇到了这个 第 3 洞 最小重复图案 编写一个子例程 它接受一个字符串 该字符串可能包含 重复模式 并返回最小的重复
  • 如何抑制spark输出控制台中的“Stage 2===>”?

    我有数据帧并试图获取不同的计数并且能够成功获取不同的计数 但是每当 scala 程序执行时我都会收到此消息 Stage 2 gt 1 1 2 我如何在控制台中抑制特定的此消息 val countID dataDF select substr
  • 如何发现 Scala 远程 Actor 已死亡?

    在 Scala 中 当另一个 远程 actor 终止时 可以通过设置 trapExit 标志并以第二个 actor 作为参数调用 link 方法来通知一个 actor 在这种情况下 当远程参与者通过调用 exit 结束其工作时 第一个参与者
  • 阶乘的 Scala 排列

    我怎样才能找到n Scala 中某些字母的排列 Scala 2 9 RC1 scala gt abc permutations toList res58 List String List abc acb bac bca cab cba
  • Source.getLines 中的默认参数错误 (Scala 2.8.0 RC1)

    假设我运行 Scala 2 8 0 RC1 以下 scala 代码应该打印出文件 c hello txt 的内容 for line lt Source fromPath c hello txt getLines println line 但
  • 为什么 exceptT 没有 MonadMask 实例?

    爱德华 克梅特例外情况图书馆不提供单子掩码 https www stackage org haddock lts 7 18 exceptions 0 8 3 Control Monad Catch html t MonadMask实例为Ex
  • Scala 和变量中的模式匹配

    我是 Scala 新手 有点想知道模式匹配是如何工作的 想象一下我有以下内容 case class Cls i Int case b Cls i gt Ok case e Cls gt Ok case f Cls gt Ok case s
  • Scala Tuple2Zipped 与 IterableLike zip

    两种实现有什么区别 这个比那个好吗 有一篇博客文章说 Tuple2Zipped 性能更好 但没有提供原因 并且查看源代码我没有看到差异 val l1 List 1 2 3 val l2 List 5 6 7 val v1 l1 zip l2
  • 使用 scala 集合 - CanBuildFrom 麻烦

    我正在尝试编写一个接受任何类型集合的方法CC 并将其映射到一个新的集合 相同的集合类型但不同的元素类型 我正在挣扎 基本上我正在尝试实施map but 不在集合本身上 问题 我正在尝试实现一个带有签名的方法 它看起来有点像 def map

随机推荐