Skip to main content
Version: 2.x

Overriding Dependency Graph

We can create a ZIO application by providing a local or a global environment, or a combination:

Global Environment

It is usual when writing ZIO applications to provide layers at the end of the world. Then we provide layers to the whole ZIO application all at once. This pattern uses a single global environment for all ZIO applications:

import zio._

object MainApp extends ZIOAppDefault {
val myApp: ZIO[ServiceA & ServiceB & ServiceC & ServiceD, Throwable, Unit] = ???

def run = myApp.provide(a, b, c, d)
}

Local Environment

Occasionally, we may need to provide different environments for different parts of our application, or it may be necessary to provide a single global environment for the entire application except for some inner layers.

Providing a layer locally is analogous to overriding a method in an object-oriented paradigm. So we can think of that as overriding the global environment:

import zio._

object MainApp extends ZIOAppDefault {
def myApp: ZIO[A & B & C, Throwable, Unit] = {
def innerApp1: ZIO[A & B & C, Throwable, Unit] = ???
def innerApp2: ZIO[A & C, Throwable, Unit] = ???

innerApp1.provideSomeLayer[A & B](localC) *> innerApp2
}

def run = myApp.provide(globalA, globalB, globalC)
}

ZIO Test's Live service uses this pattern to provide real environment to a single part of an effect.