Боюсь, вам нужно вернуть экземпляр, который реализует все характеристики, которые вы хотите предоставить.
Если вы посмотрите на пример в документации 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)
* }
* }
* )
* }}}
*/
Для меня это означает, что мне не нужно предоставлять полный тип среды, яможет добавить необходимые модули один за другим
Нет. Вы должны предоставить экземпляр полного типа среды для эффекта, который вы переносите (потому что это необходимо). Я думаю, что это потому, что мы хотим, чтобы это проверялось во время компиляции, и нет способа (без макросов) генерировать стекированную среду с «затиранием» без объяснения, как это сделать. Вероятно, в будущем будут какие-то макросы для этого.
точно так же, как .provide - так какой смысл?
Разница в том, что с .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
Для программы требовался экземпляр Console и System в среде, но мне не нужно было.provide
до
Это связано с тем, что ZEnv
среда по умолчанию уже предоставляет эти два.
Поскольку создание экземпляра регистратора в Java довольно эффективно,Является ли .provide даже правильной функцией для вызова?
Лично я бы проигнорировал, что создание логгеров эффективно. Это не похоже на то, что стоит отслеживать. Я считаю некоторым базовым средством, что это почти часть загрузки классов.
Если вы хотите отследить эффект, вы можете сделать
app
.provideSomeM(env => for {
logger <- UIO(Slf4jLogger.create)
} yield new MyEnvironment(env, logger)
)