如何在Scala中实现IO monad的短路
我使用标准的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没有定义过滤器(或withFilter),所以你不能在你的理解中使用守卫. 现在,如果你想要你所说的(相同的逻辑,只是更干),你总是可以在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 … 但如果你真的想要短路,你将不得不以某种方式分解案件.这是一种可能性,假设您只想将所有内容打包到一个数组中,因此返回类型很简单,并且您的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,io(),io()) } } 如果你允许退货,你会得到: val a = io() if (a == 1) return Array(a) val b = io() if (b == 1) return Array(a,b) Array(a,io()) 原则上也可以使用额外的方法来装饰IO monad,但是标准withFilter将不起作用,因此你将无法使用for-comprehension语法糖. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |