gpt4 book ai didi

scala - Cats-Effect 和 IO monad

转载 作者:行者123 更新时间:2023-12-01 03:21:51 24 4
gpt4 key购买 nike

我已经尝试掌握 IO monad 一段时间了,这是有道理的。如果我没记错的话,目标是将副作用的描述和实际执行分开。如下例所示,Scala 有一种方法可以获取引用不透明的环境变量。出现了两个问题。

问题 1:这是引用透明的吗

问题 2:如何正确(基于单元/属性)对此进行测试?不可能检查相等性,因为它会检查内存引用,并且不可能检查内部函数,因为如果我没记错的话,函数比较是不可能的。但是,我不想在我的单元测试中运行实际的副作用。另外,这是设计错误还是滥用 IO monad?

case class EnvironmentVariableNotFoundException(message: String) extends Exception(message)

object Env {
def get(envKey: String): IO[Try[String]] = IO.unit.flatMap((_) => IO.pure(tryGetEnv(envKey)))

private[this] def tryGetEnv(envKey: String): Try[String] =
Try(System.getenv(envKey))
.flatMap(
(x) =>
if (x == null) Failure(EnvironmentVariableNotFoundException(s"$envKey environment variable does not exist"))
else Success(x)
)
}

最佳答案

好用IO在程序中包含来自不纯源的值,就像示例中的系统调用一样。这会给你一个 IO[A]读作“我能够通过不纯的方式获得 A”。此后,您可以使用作用于该 A 的纯/引用透明函数。 , 通过 map , flatMap等等。

这导致了两个答案。我想问一下,你想测试这个的什么属性?

查看该代码,我注意到 flatMaptryGetEnv作为可能足够复杂以保证测试的东西。您可以通过将此逻辑提取到纯函数中来做到这一点。您可能(例如)重新编写它,以便有一个返回 IO[String] 的函数。然后编写一个(经过测试的)函数,将其转换为您想要的类型。

IO 完全按照你说的去做,但这明确不包括使代码引用透明!如果你想在这里测试实际的副作用,你可以考虑将 System 作为参数传递并模拟它进行测试,就像在不使用 IO 的程序中一样。 .

所以总而言之,我会考虑创建一个 最小 调用 System 的函数创建一个 IO[A] (在本例中为 IO[Try[String]] )。您可能会选择通过模拟来测试这个最小的功能,但前提是您觉得这样做可以增加值(value)。围绕这一点,您可以编写带有 A 的函数。并通过将纯值传递给这些函数来测试它们。请记住,map 的签名在 IO如下,还有f这是一个纯(可测试)函数!

sealed abstract class IO[+A] {

def map[B](f: A => B): IO[B]
^ f is a pure function!
test it by passing A values and verifying the Bs

极端情况下,这种模式鼓励您创造 IO仅在程序最边缘的值(例如您的 main 函数)。然后可以从纯函数创建程序的其余部分,这些函数作用于程序运行时来自 IO 类型的值。

关于scala - Cats-Effect 和 IO monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44569689/

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