In the monomorphic variant, the U type parameter is supplied during creation of an instance of the effect:
// `The U` is explicitly set as `IO`:
case object MyResource extends ResourceEffect[IO]
// The `U` is inferred from the effect instance:
val computation = MyResource.register(IO(println("RESOURCE CLOSED!")))
In the polymorphic variant, the U type parameter is covariantly inferred at call sites of effect's operations and handlers:
case object MyResource extends PolyResourceEffect
// auxiliary definitions, because we need 2 distinct effects:
case object S1 extends StateEffect[Boolean]; type S1 = S1.type
case object S2 extends StateEffect[Boolean]; type S2 = S2.type
val computation1 = MyResource.register(S1.put(false)) // `U` inferred as `S1`
val computation2 = MyResource.register(S2.put(false)) // `U` inferred as `S2`
val computation3 = computation1 &&! computation2 // `U` inferred as `S1 & S2`