I have the following code in my lib:
trait Statement[A] {}
trait Derivation[B]:
type Source
object Derivation:
def make[A, B](using Statement[A]) =
new Derivation[B]:
type Source = A
def check[A, B](using Derivation[B] { type Source = A }): Unit = ()
case class Foo(a: Unit)
case class Bar(b: Unit)
given Statement[Foo] = new Statement[Foo] {}
given Derivation[Bar] = Derivation.make[Foo, Bar]
Now I want this code written by user to compile:
Derivation.check[Foo, Bar]
But it doesn’t because we erased Source
in our given. User could write it as:
given Derivation[Bar] { type Source = Bar } = Derivation.make[Foo, Bar]
I don’t want to do that because it’s a user-facing code and looks ugly for someone who doesn’t want to know how the underlying lib works. The only option I have right now is to stick with Derivation[A, B]
I have two questions:
- Is there a way to avoid explicit type members and two type parameters?
- Is there a way to find all
Derivations
ofFoo
?Derivation.make
establishes Bar-to-Foo relationship, but I want to know all relationships that point to Foo, i.e. all givens ofDerivation
whereFoo
is used.