gpt4 book ai didi

scala - 如何在 Scala 中使用 IO monad 实现短路

转载 作者:行者123 更新时间:2023-12-04 12:53:39 25 4
gpt4 key购买 nike

我使用标准的 IO monad。

在某些时候,我需要短路。在给定条件下,我不想运行以下 ios。

这是我的解决方案,但我发现它太冗长且不优雅:

  def shortCircuit[A](io: IO[A], continue: Boolean) =
io.map(a => if (continue) Some(a) else None)

for {
a <- io
b <- shortCircuit(io, a == 1)
c <- shortCircuit(io, b.map(_ == 1).getOrElse(false))
d <- shortCircuit(io, b.map(_ == 1).getOrElse(false))
e <- shortCircuit(io, b.map(_ == 1).getOrElse(false))
} yield …

例如,对于第 3、4 和 5 行,我需要重复相同的条件。

有没有更好的办法 ?

最佳答案

你实际上并没有在那里短路任何东西。您仍在运行 IO;你只是没有捕捉到这些值。

此外,标准 IO monad 没有定义 filter (或 withFilter ),所以你不能在你的理解中使用守卫。

现在,如果你只想要你所说的(相同的逻辑,只是更 DRY),你总是可以在 for comprehension 中分配一个临时变量:

for {
a <- io
b <- shortCircuit(io, a == 1)
continue = b.map(_ == 1).getOrElse(false)
c <- shortCircuit(io, continue)
d <- shortCircuit(io, continue)
e <- shortCircuit(io, continue)
} yield …

但是,如果您真的想短路,则必须以某种方式拆开 shell 。这是一种可能性,假设您只想将所有内容打包到一个数组中以便返回类型很简单,而您的 IO伴生对象有一个 apply 方法,你可以用它来创建只返回一个值的东西:
io.flatMap(a =>
if (a == 1) IO(() => Array(a))
else io.flatMap(b =>
if (b == 1) IO(() => Array(a,b))
else for {
c <- io
d <- io
e <- io
} yield Array(a,b,c,d,e)
)
)

如果您的返回类型更复杂,您可能需要更加努力地指定类型。

FWIW,值得注意的是,您将事物包裹在 monad 中所付出的代价;没有,相同的逻辑将是(例如):
io() match {
case 1 => Array(1)
case a => io() match {
case 1 => Array(a, 1)
case b => Array(a, b, io(), io(), io())
}
}

如果您允许退货,您将获得:
val a = io()
if (a == 1) return Array(a)
val b = io()
if (b == 1) return Array(a, b)
Array(a, b, io(), io(), io())

原则上也可以使用额外的方法来装饰 IO monad,但标准 withFilter将不起作用,因此您将无法使用 for-comprehension 语法糖。

关于scala - 如何在 Scala 中使用 IO monad 实现短路,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29292184/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com