Reputation: 2250
I read existing questions about how type definitions with parameterized bounds are illegal inside blocks (or something to that effect), but it doesn't help me in my problem:
type Cons[X]
class Higher[C[X] <: Cons[X]]
type AnyHigher = Higher[C] forSome { type C[X] <: Cons[X] }
Seq[AnyHigher]().map { h => h }
compiler:
can't existentially abstract over parameterized type C
Seq[AnyHigher]().map { h => h }
The element type of the input collection is irrelevant, the problem lies only in the return type of the mapping function. Is there any way around this? I tried various refactors: making the mapping function a method, cheating by making the code generic and executing parameterized with AnyHigher
, writing my own recursion, but nothing helps.
Upvotes: 0
Views: 116
Reputation: 2250
Why @Dmytro Mitin's answer is the correct one as both type safe, and offering a local solution not needing changes to the types, it is a bit of a mouthful. So, at least temporarily, I opted for introducing a super type and casting:
sealed trait AnyHigher {
def apply() :Higher[T] forSome { type T[O] <: Cons[O] } =
this.asInstanceOf[Higher[T] forSome { type T[O] <: Cons[O] }]
}
class Higher[T[O] <: Cons[O]] extends AnyHigher
Seq[AnyHigher]().map(t => t)
It's ugly, but a bit less and it's temoporary until Scala 3, which has wildcard types covering any kinds.
Upvotes: 0
Reputation: 51683
A workaround is
Seq[AnyHigher]().map(new (AnyHigher => AnyHigher) {
override def apply(h: AnyHigher): AnyHigher = h
})
"can't existentially abstract over parameterized type..."
Another workaround is to make C[X]
a type member rather than type parameter
type Cons[X]
class Higher {
type C[X] <: Cons[X]
}
object Higher {
type Aux[C0[X0] <: Cons[X0]] = Higher { type C[X] = C0[X] }
}
type AnyHigher = Higher
Seq[AnyHigher]().map(h => h)
and use Higher.Aux[C]
instead of Higher[C]
and Higher
instead of Higher[C] forSome { type C[X] <: Cons[X] }
.
http://dotty.epfl.ch/docs/reference/dropped-features/existential-types.html
Existential type is a dropped feature, which makes the following code illegal.
def foo: List[Class[T]] forSome { type T }
The proposed solution is to introduce an enclosing type that carries a dependent type:
trait Bar { type T val value: List[Class[T]] } def foo: Bar
Upvotes: 2