繁体   English   中英

使用 Scala 猫效应执行副作用

[英]Performing side effects using scala cats effect

我正在尝试在 Scala 中使用猫效果,并且在世界末日我有这样的类型: IO[Vector[IO[Vector[IO[Unit]]]]]

我发现只有一种方法来运行它:

for {
    row <- rows.unsafeRunSync()
} yield
 for {
   cell <- row.unsafeRunSync()
 } yield cell.handleErrorWith(errorHandlingFunc).unsafeRunSync()

但它看起来非常丑陋。 请帮助我了解如何执行复杂的副作用。

更新:

1)第一个IO - 我打开 excel 文件并获取行向量,即IO[Vector[Row]]

2)第二次IO - 我对每一行执行数据库查询。 我无法用Vector[_]组合 IO monad,

3)第三个IO - 我使用来自 DB 的Vector[Results]为 excel 的每一行创建 PDF 文件。

所以我有这样的功能:

1) String=>IO[Vector[Row]]

2) Row=>IO[Vector[Results]]

3) Vector[Results] => IO[Unit]

举个例子,这是我刚刚用相同类型的头顶制作的一个无意义的动作:

import cats.effect.IO

val actions: IO[Vector[IO[Vector[IO[Unit]]]]] =
  IO(readLine).flatMap(in => IO(in.toInt)).map { count =>
    (0 until count).toVector.map { _ =>
      IO(System.nanoTime).map { t =>
        (0 until 2).toVector.map { _ =>
          IO(println(t.toString))
        }
      }
    }
  }

这里我们从标准输入中读取一个字符串,将它解析为一个整数,多次查看当前时间,并且每次打印两次。

展平这种类型的正确方法是使用sequence来重新排列图层:

import cats.implicits._

val program = actions.flatMap(_.sequence).flatMap(_.flatten.sequence_)

(或者类似的东西——你可以用很多合理的方式来写这个。)

该程序的类型为IO[Unit] ,并且按我们的预期工作:

scala> program.unsafeRunSync
// I typed "3" here
8058983807657
8058983807657
8058984254443
8058984254443
8058984270434
8058984270434

但是,每当您看到涉及多层IO和集合的深度嵌套类型时,最好的做法很可能是首先避免陷入这种情况(通常使用traverse )。 在这种情况下,我们可以像这样重写我们的原始actions

val actions: IO[Unit] =
  IO(readLine).flatMap(in => IO(in.toInt)).flatMap { count =>
    (0 until count).toVector.traverse_ { _ =>
      IO(System.nanoTime).flatMap { t =>
        (0 until 2).toVector.traverse { _ =>
          IO(println(t.toString))
        }
      }
    }
  }

这将与我们的program完全相同的方式工作,但是我们通过将原始actionsmap替换为flatMaptraverse避免嵌套。 知道你需要什么是你通过练习学到的东西,但是当你开始时,最好尽可能地采取最小的步骤并遵循类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM