scala extending trait with methods returing various types, types mismatch

Viewed 41

I do something like this:

sealed trait Foo[T] {
  def getA: Decoder[T]
  def getB: Either[Type1, Type2]
}

trait Hello[T] extends Foo[T] {
  def getA: Decoder[T]
  def getB: Type1
}

trait World[T] extends Foo[T] {
  def getA: Decoder[T]
  def getB: Type2
}

Currently, Either is wrong way to define all types. How to solve it?

1 Answers

You can try to narrow return type in child traits

trait Hello[T] extends Foo[T] {
  def getA: Decoder[T]
  def getB: Left[Type1, Type2]
}

trait World[T] extends Foo[T] {
  def getA: Decoder[T]
  def getB: Right[Type1, Type2]
}

Or you can try to introduce a type member

sealed trait Foo[T] {
  def getA: Decoder[T]
  type Out
  def getB: Out
}

trait Hello[T] extends Foo[T] {
  def getA: Decoder[T]
  type Out = Type1
  def getB: Type1
}

trait World[T] extends Foo[T] {
  def getA: Decoder[T]
  type Out = Type2
  def getB: Type2
}

Or you can try a type class

sealed trait Foo[T] {
  type This <: Foo[T]
  def getA: Decoder[T]
  def getB(implicit tc: TC[T, This]): tc.Out
}

trait Hello[T] extends Foo[T] {
  type This <: Hello[T]
  def getA: Decoder[T]
}

trait World[T] extends Foo[T] {
  type This <: World[T]
  def getA: Decoder[T]
}

trait TC[T, F <: Foo[T]] {
  type Out
}
object TC {
  implicit def hello[T, F <: Hello[T]]: TC[T, F] { type Out = Type1 } = null
  implicit def world[T, F <: World[T]]: TC[T, F] { type Out = Type2 } = null
}
Related