final def ensuring[R1 <: R](finalizer: URIO[R1, Any]): ZIO[R1, E, A]
ensuring is a combinator available on all zio values
since it is a combinator, it can combine two zio values,
the first with the second (the finalizer) to yield the third (the composite) description
the second zio, is an effect, and
it is not allowed to fail
it can bring in its additional environmental dependencies
what's up with R and R1 ??
R is of the first effect
R1 is of the composite effect
when running the composite effect, the environment the composite effect is provided, should cater to the requirements of both, the first effect AND the finalizer
ie, the provided environment should be usable as both, the environment for the first effect AND that of the finalizer
if we constrain R1 to be a subtype of R, then an r1: R1 can be used as R,
thus R1 can cater to the requirements of first effect
,
// but how do we reconcile with the type the finalizer comes with and what's inferred?
example
let's say the first effect has dependency on Random and the finalizer has dependency on Console then the composite effect has to have a dependency on both Random AND Console
val z1: URIO[Random, Int] = nextInt
val z2: URIO[Console, Unit] = putStrLn("hi")
val z3: URIO[Random & Console, Int] = z1.ensuring(z2)
a value of type Random & Console can be used as both, Random or Console because it is a subtype of Random and it is a subtype of Console.
final def ensuring[R1 <: R](finalizer: URIO[R1, Any]): ZIO[R1, E, A]
what's up with R and R1 ??
example
Random
and the finalizer has dependency onConsole
then the composite effect has to have a dependency on bothRandom
ANDConsole
a value of type
Random & Console
can be used as both,Random
orConsole
because it is a subtype of Random and it is a subtype of Console.