我用的是标准的IO单。
在某种程度上,我需要短路。在给定条件下,我不想运行以下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行,我需要重复相同的条件。
有更好的办法吗?
发布于 2015-03-27 21:20:46
你在那里什么都没短路。您仍然在运行IOs;只是不捕获值。
此外,标准的IO monad没有定义filter (或withFilter),因此您不能在理解过程中使用保护。
现在,如果您想要的只是您所说的(相同的逻辑,只是更枯燥),您可以始终指定一个临时变量中的理解:
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 …但是如果你真的想要短路,你就必须在某种程度上打破这些情况。这里有一种可能性,假设您只想将所有内容打包到一个数组中,因此返回类型是简单的,并且您的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,值得注意的是,如果不使用单片包装的东西,就需要付出代价(例如):
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无法工作,所以您将无法使用理解语法糖。
https://stackoverflow.com/questions/29292184
复制相似问题