开发者

Accessing type-parameter of a type-parameter

开发者 https://www.devze.com 2023-02-02 09:55 出处:网络
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 fol

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]] {})
                             ^
0

精彩评论

暂无评论...
验证码 换一张
取 消