Problems with Dependent Method Type

62 views Asked by At

Consider the following code: Why is S.|.NotOrNot.OUT not equal to S.Not?

sealed trait S
object S {
  trait Not extends S
  trait A extends S
  trait B extends S
  trait C extends S
  trait |[X <: S, Y <: S] { type OUT <: S }
  trait LowerPriorityImplicits {
    // implicit def XorNot[X <: S] = |[X, Not, X]
    // implicit def NotOrX[X <: S] = |[Not, X, X]
  }
  object | extends LowerPriorityImplicits {
    def apply[X <: S, Y <: S, Z <: S]: X | Y = new |[X, Y] { type OUT = Z }
    // implicit def XorX[X <: S] = |[X, X, X]
    implicit lazy val NotOrNot = |[Not, Not, Not]
  }
}

import S._
def foo[X <: S, Y <: S](implicit ev: X | Y): ev.OUT = null.asInstanceOf[ev.OUT]
val bar = foo[Not, Not]
val baz: Not = foo[Not, Not] // found: S.|.NotOrNot.OUT  required: S.Not

EDIT :

Or a condensed example:

trait T { type Out }
object T {
  def apply[X]: T = new T { type Out = X }  
}
val t = T[Int]
val i: t.Out = 5 // found: Int(5)  required: t.Out

But this runs fine:

trait T[O] { type Out = O }
object T {
  def apply[X]: T[X] = new T[X] {}
}
val t = T[Int]
val i: t.Out = 5
1

There are 1 answers

0
0__ On BEST ANSWER

Your apply method says the return type is T, that is type member Out is unspecified.

The following specifies the type completely:

trait T { type Out }
object T {
  def apply[X]: T { type Out = X } = new T { type Out = X }  
}
val t = T[Int]
val i: t.Out = 5 // ok