gpt4 book ai didi

scala - ZIO环境 build

转载 作者:行者123 更新时间:2023-12-01 11:12:25 30 4
gpt4 key购买 nike

我开始尝试使用 ZIO,并尝试运行以下高度复杂的程序:

import logger.{Logger, _}
import zio.console._
import zio.{system, _}

object MyApp extends App {

override def run(args: List[String]): ZIO[ZEnv, Nothing, Int] = {

app
.provideSome[Logger](_ => Slf4jLogger.create) //1
.fold(_ => 1, _ => 0)
}

val app: ZIO[Console with system.System with Logger, SecurityException, Unit] =
for {
_ <- info("This message from the logger") //2
maybeUser <- system.env("USER")
_ <- maybeUser match {
case Some(userName) => putStrLn(s"Hello ${userName}!")
case None => putStrLn("I don't know your name")
}
} yield ()
}

(Slf4jLogger 是 https://github.com/NeQuissimus/zio-slf4j )

如果我评论行 //1//2一切正常。但在上面的表格中,我得到一个类型不匹配的错误:
Error:(13, 45) type mismatch;
found : logger.Slf4jLogger
required: zio.console.Console with zio.system.System with logger.Logger
.provideSome[Logger](_ => Slf4jLogger.create)

我不明白以下内容:
  • 该程序需要 ConsoleSystem环境中的实例,但我不必.provide以前,当我没有登录时。为什么?为什么我突然需要它?
  • 根据 scaladoc,.provideSome提供运行此效果所需的*一些*环境,剩下的为 R0。对我来说,这意味着我不必提供完整的环境类型,我可以一个一个地添加所需的模块 - 但似乎需要完整的 ZEnv 类型,就像 .provide - 那有什么意义呢?
  • 我无法通过 new Logger with Console.Live with system.System.Live 实例化匿名类,因为 Slf4jLogger 在伴生对象中有一个工厂方法。如何将此工厂方法与其他特征一起使用?
  • 由于在 Java 中创建记录器实例是一种有效的方法,因此 .provide甚至调用正确的函数?

  • PS:我能够以一种丑陋的方式让它工作:
        app
    .provideSome[ZEnv](_ =>
    new Console with Logger with system.System {
    override val console = Console.Live.console
    override val system = System.Live.system
    override val logger = Slf4jLogger.create.logger
    }
    ) //1
    .fold(_ => 1, _ => 0)

    这编译并运行,但覆盖混合特征的内部成员似乎不正确......

    它的工作方式与 .provide 完全相同。 :
        app
    .provide(
    new Console with Logger with system.System {
    override val console = Console.Live.console
    override val system = System.Live.system
    override val logger = Slf4jLogger.create.logger
    }
    ) //1
    .fold(_ => 1, _ => 0)

    到底是怎么回事?

    最佳答案

    恐怕您必须返回一个实现您要提供的所有特征的实例。

    如果您查看 ZIO 文档中的示例 provideSome ,您会看到他们正在做完全相同的事情:他们正在采取Console并将其变成 Console with Logging .

    /**
    * Provides some of the environment required to run this effect,
    * leaving the remainder `R0`.
    *
    * {{{
    * val effect: ZIO[Console with Logging, Nothing, Unit] = ???
    *
    * effect.provideSome[Console](console =>
    * new Console with Logging {
    * val console = console
    * val logging = new Logging {
    * def log(line: String) = console.putStrLn(line)
    * }
    * }
    * )
    * }}}
    */

    For me that means that I don't have to provide the full environment type, I could add the required modules one by one



    不,您必须提供一个完整环境类型的实例来实现您包装的效果(因为它需要它)。我认为这是因为我们希望在编译时对其进行检查,并且没有办法(没有宏)生成“混搭”堆叠环境而不详细说明如何做到这一点。 future 可能会有一些宏。

    just like .provide - so what's the point?



    不同之处在于 .provide您必须在没有任何输入的情况下从头开始构建所需环境的实例。因此,效果(用你的包装)不再需要任何东西。

    .provideSome您自己可以请求一个环境来帮助您构建您提供的实例。该环境将被传递到您的函数中。在上面的示例中,它们需要 Console并将其扩充为 Console with Logging (通过使用 console 给出的实例)。结果, effect.provideSome[Console](...)仍然需要 Console (而用 .provide 编写,则需要 Nothing )。
    .provideSome[ZEnv](_ =>
    new Console with Logger with system.System {
    override val console = Console.Live.console

    由于您使用的是 provideSome[ZEnv] ,您可能不应该访问全局单例 Console.Live ,但取自 env被传入:
    .provideSome[ZEnv](env =>
    new Console with Logger with system.System {
    override val console = env.console

    The program required a Console and a System instance in the environment, yet I did not have to .provide it before



    那是因为 ZEnv ,默认环境已经提供了这两个。

    Since creating a logger instance in Java is kind of effectful, is .provide even the right function to call?



    就个人而言,我会忽略构建记录器是有效的。这似乎不值得追踪。我认为它是一些基本功能,它几乎是类加载的一部分。

    如果你确实想跟踪效果,你可以这样做
    app
    .provideSomeM(env => for {
    logger <- UIO(Slf4jLogger.create)
    } yield new MyEnvironment(env, logger)
    )

    关于scala - ZIO环境 build ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58536841/

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