With simple ZIO layer creation, it’s convenient to use +`, `>>>` and `>> to compose layers.

When layers and dependencies get more complex, ZLayer.make is there to help.

For example, we want to build a Robot.

We have our domain

case class Screw()
case class Arm(screw: Screw)
case class Leg(screw: Screw)
case class Robot(arm: Arm, leg: Leg, screw)

And the layers to build them using parts

val screwLayer: ZLayer[Any, Nothing, Screw] = ZLayer.succeed(Screw())
val armLayer: ZLayer[Screw, Nothing, Arm] = ZLayer.fromFunction(Arm(_))
val legLayer: ZLayer[Screw, Nothing, Leg] = ZLayer.fromFunction(Leg(_))
val robotLayer: ZLayer[Arm with Leg with Screw, Nothing, Robot] = ZLayer.fromFunction(Robot(_, _))

Then we can assemble the whole Robot from scratch

val robotFromScratchLayer: ZLayer[Any, Nothing, Robot] =
  screwLayer >+> (armLayer ++ legLayer) >>> robotLayer

This can be simplified using ZLayer.make

val robotFromScratchLayer: ZLayer[Any, Nothing, Robot] =
  ZLayer.make[Robot](screwLayer, armLayer, legLayer, robotLayer)

ZIO will figure out how exactly it can wire these layers to create the desired result.