Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 522
0__ Avatar asked Apr 03 '11 04:04

0__


2 Answers

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]})#λ]
like image 128
Moritz Avatar answered Sep 18 '22 10:09

Moritz


googling for "partial type application" i found this solution posted by James Iry on the scala debate list ( http://scala-programming-language.1934581.n4.nabble.com/Partial-type-inference-td2007311.html ; adapted so the arg order is changed):

type Partial2[T[_,_], B] = {
   type Apply[A] = T[A,B]
}
trait CList[C1, A] extends Access[Partial2[CList, A]#Apply]

cheese louise, is this really the only way to do that in scala in 2011 ?!!

EDIT:

This fails with covariance in A :,-(

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

type Partial2[T[_,_], B] = {
  type Apply[A] = T[A,B]
}
trait CList[C1, +A] extends Access[Partial2[CList, A]#Apply]

"covariant type A occurs in invariant position"
like image 31
0__ Avatar answered Sep 21 '22 10:09

0__