How to do dependent implicit typing?


#1

How to do a transformation, where an implicit value depends on the actual underlying type of another implicit value?

For one level, where the result type depends only on the input type:

trait Foo[T]
def giveMeFoo[T](implicit f: Foo[T]): f.type = ???

Ok, this is easy and works as expected.
However, when we go one more level, this doesn’t work:

trait Foo[T]
trait Bar[T]
def giveMeBar[T](implicit foo: Foo[T], bar: Bar[foo.type]): bar.type = ???

or maybe like this:

def giveMeBar[T](implicit foo: Foo[T])(implicit bar: Bar[foo.type]): bar.type = ???

Unfortunately there is only one implicit param list allowed :frowning:

Is there any pattern around this limitation?

I also tried to take approach similar to this:

implicit def giveMeBar[T, F <: Foo[T], B <: Bar[F]](implicit foo: F, bar: B): SomethingParameterizedWith[T, F, B] = ???

But this failed to my surprise with “diverging implicits”. I guess the problem with diverging implicits is that it tries to evaluate all implicits at once and some types are really unconstrained, and it can only work backwards from the result. If the result type is complex, it is hard to even follow, how the type resolution should work here.

In my case I know the input type T, and just want to follow implicit chain from it, because there is only one implicit Foo[T], one Bar[Foo[T]] and so on. But I want real underlying types there (foo.type), not the general ones like Foo[T] (for general ones it is trivial).

This is not what I want:

def giveMeBar[T](implicit foo: Foo[T], bar: Bar[Foo[T]]): Bar[T] = ???

#2

Noone answered, but it looks like I found a solution: the Aux pattern. Described here: http://gigiigig.github.io/posts/2015/09/13/aux-pattern.html