如何在 ZIO 中优雅地组合多个包含选项的任务
How to elegantly combine multiple Tasks containing options in ZIO
我正在寻找
的最优雅的实现
import scalaz.zio.Task
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D)
: Task[Option[D]]
使用
- 没有额外的依赖项
scalaz-zio-interop-cats
和 cats
scalaz-zio-interop-scalaz7x
和 scalaz7x
解决方案应该很好地推广到 n 个参数。
对于猫,您可以使用 mapN
组合多个选项。所以这会起作用:
import cats._
import cats.implicits._
val o1 = 1.some
val o2 = 2.some
val o3 = 3.some
(o1,o2,o3).mapN((a,b,c) => a |+| b |+| c) // Some(6)
剩下要做的就是展开任务,因为它们是 monad,你可以做:
for {
t1 <- task1
t2 <- task2
t3 <- task3
} yield (t1,t2,t3)
.mapN((a,b,c) => /* combine a,b,c */)
在获得一些帮助并进行研究后,我发现了以下实现,这些实现对我来说是迄今为止最优雅的:
1.不使用额外的依赖项:
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D)
: Task[Option[D]] = {
for {
t1 <- task1
t2 <- task2
t3 <- task3
} yield {
(t1, t2, t3) match {
case (Some(t1), Some(t2), Some(t3)) => Some(f(t1, t2, t3))
case _ => None
}
}
}
2。使用 scalaz-zio-interop-cats
和 cats
:
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D)
: Task[Option[D]] = {
import cats.implicits.catsStdInstancesForOption
import cats.Apply
import scalaz.zio.interop.catz._
Apply[Task].compose[Option].map3(task1, task2, task3)(f)
}
有关相关讨论,请参阅 。
3。使用 scalaz-zio-interop-scalaz7x
和 scalaz7x
:
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D): Task[Option[D]] = {
import scalaz.Apply
import scalaz.std.option._
import scalaz.zio.interop.scalaz72._
Apply[Task].compose[Option].apply3(task1, task2, task3)(f)
}
我正在寻找
的最优雅的实现import scalaz.zio.Task
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D)
: Task[Option[D]]
使用
- 没有额外的依赖项
scalaz-zio-interop-cats
和cats
scalaz-zio-interop-scalaz7x
和scalaz7x
解决方案应该很好地推广到 n 个参数。
对于猫,您可以使用 mapN
组合多个选项。所以这会起作用:
import cats._
import cats.implicits._
val o1 = 1.some
val o2 = 2.some
val o3 = 3.some
(o1,o2,o3).mapN((a,b,c) => a |+| b |+| c) // Some(6)
剩下要做的就是展开任务,因为它们是 monad,你可以做:
for {
t1 <- task1
t2 <- task2
t3 <- task3
} yield (t1,t2,t3)
.mapN((a,b,c) => /* combine a,b,c */)
在获得一些帮助并进行研究后,我发现了以下实现,这些实现对我来说是迄今为止最优雅的:
1.不使用额外的依赖项:
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D)
: Task[Option[D]] = {
for {
t1 <- task1
t2 <- task2
t3 <- task3
} yield {
(t1, t2, t3) match {
case (Some(t1), Some(t2), Some(t3)) => Some(f(t1, t2, t3))
case _ => None
}
}
}
2。使用 scalaz-zio-interop-cats
和 cats
:
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D)
: Task[Option[D]] = {
import cats.implicits.catsStdInstancesForOption
import cats.Apply
import scalaz.zio.interop.catz._
Apply[Task].compose[Option].map3(task1, task2, task3)(f)
}
有关相关讨论,请参阅
3。使用 scalaz-zio-interop-scalaz7x
和 scalaz7x
:
def combineTasks[A, B, C, D](task1: Task[Option[A]],
task2: Task[Option[B]],
task3: Task[Option[C]])
(f: (A, B, C) => D): Task[Option[D]] = {
import scalaz.Apply
import scalaz.std.option._
import scalaz.zio.interop.scalaz72._
Apply[Task].compose[Option].apply3(task1, task2, task3)(f)
}