Проблемы с типом зависимого метода

#scala #dependent-method-type

#scala #dependent-method-type

Вопрос:

Рассмотрим следующий код: почему S.|.NotOrNot.OUT не равно 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
  

Редактировать :

Или сжатый пример:

 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
  

Но это работает нормально:

 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:

В вашем apply методе указано, что возвращаемый тип равен T , то есть член типа Out не указан.

Ниже указан тип полностью:

 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