score:3

Accepted answer

Maybe you want the return type to be wider than this.type but narrower than just MaxPQ[U]. Then try to introduce a type member

sealed trait MaxPQ[+U] {
  type This <: MaxPQ[U]
  // type This >: this.type <: MaxPQ[U] { type This = MaxPQ.this.This }

  def insert[K >: U : Ordering](v: K): This
}

abstract class AbstractMaxPQ[U : Ordering] extends MaxPQ[U] {
  override type This <: AbstractMaxPQ[U]
  // override type This >: this.type <: AbstractMaxPQ[U] { type This = AbstractMaxPQ.this.This }
} 

class ArrayMaxPQ[U : Ordering : ClassTag] extends AbstractMaxPQ[U] {
  override type This = ArrayMaxPQ[U]

  override def insert[K >: U : Ordering](v: K): ArrayMaxPQ[U] = ???
}

Returning the "Current" Type in Scala


If you want the return type to be parametrized with an upper bound of U try to make This higher-kinded

sealed trait MaxPQ[+U] {
  type This[K >: U] <: MaxPQ[K]
  // type This[K >: U] <: MaxPQ[K] { type This[K1 >: K] = MaxPQ.this.This[K1] }

  def insert[K >: U : Ordering](v: K): This[K]
}

abstract class AbstractMaxPQ[U : Ordering] extends MaxPQ[U] {
  override type This[K >: U] <: AbstractMaxPQ[K]
  // override type This[K >: U] <: AbstractMaxPQ[K] { type This[K1 >: K] = AbstractMaxPQ.this.This[K1] }
}

class ArrayMaxPQ[U : Ordering : ClassTag] extends AbstractMaxPQ[U] {
  override type This[K >: U] = ArrayMaxPQ[K]

  override def insert[K >: U : Ordering](v: K): ArrayMaxPQ[K] = ???
}

score:3

You can actually use higher-kinded types to do this. It's called F-bounded polymorphism.

sealed trait MaxPQ[+U, F[_]] { self: F[_ <: U] =>
  def insert[K >: U: Ordering](v: K): F[K]
}

abstract class AbstractMaxPQ[U: Ordering, F[_]] extends MaxPQ[U, F] {
  self: F[U] =>
}

class ArrayMaxPQ[U: Ordering: ClassTag] extends AbstractMaxPQ[U, ArrayMaxPQ] {
  override def insert[K >: U: Ordering](v: K): ArrayMaxPQ[K] = ???
}

Scastie demo

Instead of passing G into insert, use it as a type parameter of the class/trait itself, and then make sure that this extends that. That's what the self-type is for (self: F[U]). Another useful question


Related Query

More Query from same tag