Last active
June 24, 2021 14:17
-
-
Save strobe/6c8c860e442318ad0577cea4255e0507 to your computer and use it in GitHub Desktop.
DI with zio ZLayer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// val ZIOVersion = "1.0.0-RC17+319-8917936d-SNAPSHOT" | |
// resolvers += Resolver.sonatypeRepo("snapshots") | |
// | |
// libraryDependencies ++= Seq( | |
// // zio | |
// "dev.zio" %% "zio" % ZIOVersion, | |
// "dev.zio" %% "zio-streams" % ZIOVersion, | |
// ) | |
import zio._ | |
import zio.console._ | |
import zio.clock._ | |
import java.io.IOException | |
import zio.duration.Duration | |
import zio.duration.Duration._ | |
package object moduleA { | |
type ModuleA = Has[ModuleA.Service] | |
object ModuleA { | |
trait Service { | |
def letsGoA(v: Int): UIO[String] | |
} | |
val any: ZLayer[ModuleA, Nothing, ModuleA] = | |
ZLayer.requires[ModuleA] | |
val live: ZLayer.NoDeps[Nothing, ModuleA] = ZLayer.succeed { | |
new Service { | |
def letsGoA(v: Int): UIO[String] = UIO(s"done: v = $v ") | |
} | |
} | |
} | |
def letsGoA(v: Int): ZIO[ModuleA, Nothing, String] = | |
ZIO.accessM(_.get.letsGoA(v)) | |
} | |
import moduleA._ | |
package object moduleB { | |
type ModuleB = Has[ModuleB.Service] | |
object ModuleB { | |
trait Service { | |
def letsGoB(v: Int): UIO[String] | |
} | |
val any: ZLayer[ModuleB, Nothing, ModuleB] = | |
ZLayer.requires[ModuleB] | |
val live: ZLayer[ModuleA, Nothing, ModuleB] = ZLayer.fromService { (moduleA: ModuleA.Service) => | |
Has(new Service { | |
def letsGoB(v: Int): UIO[String] = | |
moduleA.letsGoA(v) | |
}) | |
} | |
} | |
def letsGoB(v: Int): ZIO[ModuleB, Nothing, String] = | |
ZIO.accessM(_.get.letsGoB(v)) | |
} | |
object ZLayersApp extends zio.App { | |
import moduleB._ | |
val env = Console.live ++ Clock.live ++ (ModuleA.live >>> ModuleB.live) | |
val program: ZIO[Console with Clock with Service, IOException, Unit] = | |
for { | |
_ <- putStrLn(s"Welcome to ZIO!") | |
_ <- sleep(Finite(1000)) | |
r <- letsGoB(10) | |
_ <- putStrLn(r) | |
} yield () | |
def run(args: List[String]) = | |
program.provideLayer(env).fold(_ => 1, _ => 0) | |
} | |
// output: | |
// [info] running ZLayersApp | |
// Welcome to ZIO! | |
// done: v = 10 |
Thanks.
Originally I asked the same question so here is an answer of Adam Fraser from ZIO discord:
The any environments can be useful when you want to express that you layer contains a certain value but just passes another value unchanged from a higher layer.
For example, here is an example of providing the Size module to a generator while leaving the Random module outstanding:
def provideSize[A](zio: ZIO[Random with Sized, Nothing, A])(n: Int): ZIO[Random, Nothing, A] =
zio.provideLayer[Nothing, Random, Random with Sized](Random.any ++ Sized.live(n))
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi,
Thank you very much for this short contained example ! It really helped lowering the entry barrier into ZLayers.
What would be the purpose of the val any ? My slightly tweaked example runs fine without it.
Cheers,