简体   繁体   中英

Accessing type-parameter of a type-parameter

i would like to access, in a trait, the type-parameter of a type-parameter of that trait. without adding this "second-order" type-parameter as another "first-order" parameter to the trait. the following illustrates this problem:

sealed trait A; sealed trait A1 extends A; sealed trait A2 extends A
trait B[ ASpecific <: A ] { type ASpec = ASpecific }
trait D[ ASpecific <: A ] extends B[ ASpecific ]
trait C[ +BSpecific <: B[ _ <: A ]] {
   def unaryOp : C[ D[ BSpecific#ASpec ]]
}

def test( c: C[ B[ A1 ]]) : C[ D[ A1 ]] = c.unaryOp

the test fails to compile because apparently, the c.unaryOp has a result of type C[D[A]] and not C[D[A1]], indicating that ASpec is merely a shortcut for _ <: A and does not refer to the specific type parameter.

the two-type-parameter solution is simple:

sealed trait A; sealed trait A1 extends A; sealed trait A2 extends A
trait B[ ASpecific <: A ]
trait D[ ASpecific <: A ] extends B[ ASpecific ]
trait C[ ASpecific <: A, +BSpecific <: B[ ASpecific ]] {
   def unaryOp : C[ ASpecific, D[ ASpecific ]]
}

def test( c: C[ A1, B[ A1 ]]) : C[ A1, D[ A1 ]] = c.unaryOp

but i don't understand why i need to clutter my source with this second, obviously redundant, parameter. is there no way to retrieve it from trait B?

I could make it compile by adding a type alias in C :

sealed trait A; sealed trait A1 extends A; sealed trait A2 extends A
trait B[ ASpecific <: A ] { type ASpec = ASpecific }
trait D[ ASpecific <: A ] extends B[ ASpecific ]
trait C[ +BSpecific <: B[ _ <: A ]] {
   type BSpec = BSpecific#ASpec
   def unaryOp : C[ D[ BSpec ]]
}
def test[X <: C[ B[ A1 ]]](c:X): C[ D[ X#BSpec ]] = c.unaryOp

Another enhanced version of test:

def test2[K <: A, X <: C[ B[ K ]]](c:X): C[ D[ X#BSpec ]] = c.unaryOp

Hope it haven't changed your intention.

@pedrofurla (sorry can't reply directly as i asked without being logged in)

although your example compiles, i think you are not getting anything from that but C[D[A]] because precisely X#BSpec being an alias for _ <: A ...

val x: C[D[A1]] = test(new C[B[A1]] {})

<console>:34: error: type mismatch;
 found   : C[D[A]]
 required: C[D[A1]]
       val x: C[D[A1]] = test(new C[B[A1]] {})
                             ^

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM