-
Couldn't load subscription status.
- Fork 1.4k
Description
In zio-grpc, users can define traits that take two type parameters:
trait MyService[R,C] {
def method1(req: Request): ZIO[R with C, Status, Response]
}
Where R represents an environment needed by all the service methods, and C represents metadata that the service is expecting (value changes on each request). Both R and C should be be either a subclass of zio.Has[_] or Any.
The library provides a few operations that allow doing all sort of transformations over R and C separately. For example,
trasformContext[R,C,R1](s: MyService[R,C], f: R1=>R): MyService[R1, C]
To implement those transformations 4 cases need to be considered : R and C are (Any, Any), (Any, Has[]), (Has[], Any), (Has[], Has[]). This leads to some repetition. To avoid the repetition I wrote the following typeclass that let me handle the 4 cases uniformly:
sealed trait Combinable[R, C] {
def union(r: R, c: C): R with C
}
object Combinable {
implicit def anyAny: Combinable[Any, Any] =
new Combinable[Any, Any] {
def union(r: Any, c: Any): Any = r
}
implicit def anyHas[C <: Has[_]]: Combinable[Any, C] =
new Combinable[Any, C] {
def union(r: Any, c: C): C = c
}
implicit def hasAny[R <: Has[_]]: Combinable[R, Any] =
new Combinable[R, Any] {
def union(r: R, c: Any): R = r
}
implicit def hasHas[R <: Has[_], C <: Has[_]: Tag]: Combinable[R, C] =
new Combinable[R, C] {
def union(r: R, c: C): R with C = r.union[C](c)
}
}
And using it whenever I need to union over R and C without any constraints on them. It's somewhat similar to the already existing are AreHas that addresses a similar problem.
It would be nice to consider a way to have something in ZIO to address situations like this. That Combinable would do, or possibly a superclass of Has[_] that can replace Any and would act as zero for union.