Skip to content

Instantly share code, notes, and snippets.

@strobe
Last active June 24, 2021 14:17
Show Gist options
  • Save strobe/6c8c860e442318ad0577cea4255e0507 to your computer and use it in GitHub Desktop.
Save strobe/6c8c860e442318ad0577cea4255e0507 to your computer and use it in GitHub Desktop.
DI with zio ZLayer
// 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
@fcabouat
Copy link

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,

@strobe
Copy link
Author

strobe commented Feb 25, 2020

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