Scala Abstract Type Elements - Inheritance and Type Constraints

I came across some strange situation in Scala today when I tried to clarify type restrictions in an abstract type member.

I have two traits that define the boundaries of an element of a type and combine them in a particular class. This works fine, but when matching / casting with a combination of tags, only one of the two TypeBounds is “active”, and I cannot understand why ...

I tried to prepare an example:

trait L
trait R

trait Left {
  type T <: L
  def get: T
}

trait Right {
  type T <: R
}

now if i combine these two features in one particular class

val concrete = new Left with Right {
  override type T = L with R
  override def get: T = new L with R {}
}

I can access my member via get as intended

// works fine
val x1: L with R = concrete.get

( ) , . , , .

// can only access as R, L with R won't work
val x2: R = concrete.asInstanceOf[Left with Right].get

// can only access as L, L with R won' work
val x3: L = concrete.asInstanceOf[Right with Left].get

, Left with Right - , Right Left, , ?

- , ?

+4
2

.

trait L
trait R

trait Left {
  type T <: L
  def get: T
}

trait Right {
  type T <: R
}

object X {
  type LR = Left with Right // Right#T overrides Left#T, LR#T is now <: R
  type RL = Right with Left // Left#T overrides Right#T, LR#T is now <: L

  val concrete = new Left with Right {
    override type T = L with R
    override def get: T = new L with R {}
  }

  // ok
  val r: R = concrete.asInstanceOf[LR].get
  val l: L = concrete.asInstanceOf[RL].get

  // ok
  implicitly[LR#T <:< R]
  implicitly[RL#T <:< L]

  // doesn't compile, LR#T is a subclass of R because Right#T overrides Left#T
  implicitly[LR#T <:< L]
  // doesn't compile, RL#T is a subclass of L because Left#T overrides Right#T
  implicitly[RL#T <:< R]
}

"" L with R, Left with Right, , T _ <: L _ <: R .

, (, LR RL), , . , RL LR, LR RL, , .

+8

TrustNoOne . with, .

  trait L
  trait R
  trait Base {
    type T
    def get: T
  }
  trait Nil extends Base{
    type T = Any
  }
  trait ~+~[X[_ <: Base] <: Base, Y[_ <: Base] <: Base] extends Base {
    type T = Y[X[Nil]]#T
  }
  trait Left[B <: Base] extends Base {
    type T = B#T with L
  }
  trait Right[B <: Base] extends Base {
    type T = B#T with R
  }
  val concrete = new (Left ~+~ Right) {
    def get: T = new L with R {}
  }

  val x1: L with R = concrete.get
  val x2: R = concrete.asInstanceOf[Left ~+~ Right].get
  val x3: L = concrete.asInstanceOf[Right ~+~ Left].get

, , , , Base , HList

+3

All Articles