Search code examples
scalahigher-kinded-types

Partially applying type parameters


I'm desperately trying to solve the following:

trait Access[Res[_]] { def access[C]: Res[C] }

trait CList[C1, A] extends Access[CList[_, A]] // ?!

def test[C1, C2, A](c: CList[C1, A]): CList[C2, A] = c.access[C2]

scalac just says: "error: illegal cyclic reference involving trait CList". how can I make this compile?


Solution

  • You might be interested in type lambdas. The partial application you used in your answer is actually implemented in scalaz. As the code tends to get less readable though, they started using type lambdas instead. The type in question could be written as

    ({type λ[α] = CList[α,A]})#λ
    

    This works by creating a type projection on a parameterized type λ inside a structural type thus capturing the outer type parameter (in this case A).

    The other problem concerning variance described in your answer could be solved by making the Res parameter in Access covariant.

    After these changes your code should look like this:

    trait Access[+Res[_]] { def access[C] : Res[C]}
    
    trait CList[C, +A] extends Access[({type λ[α] = CList[α,A]})#λ]