1

I was trying to implement a similar structure with an idea to have a common trait to work with different Input instances regardless of their InType.

trait AnyInput {
    type InType
    val obj : InType
}

abstract class Input[T](obj: T) extends AnyInput {
    type InType = T
}

case class InpImage(image: ByteStream) extends Input[ByteStream](image)
case class InpString(text: String) extends Input[String](text)
.
.
.

trait InputProcessor[T <: Input[T#InType]] {
    ...
}

and I get the "cyclic reference involving type T error" in the InputProcessor definition

It is important to notice, that there might be a couple different case class implementing Input[String] or Input[ByteStream]. So writing it out as

case class StringInput(s: String) extends Input[String](s)
case class IntInput(numb: Int) extends Input[Int](numb)

is not the best workaround

Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Martee
  • 77
  • 10

2 Answers2

1

Maybe you can use

trait InputProcessor[S, T <: Input[S]] {
   // ...
}
Yuval Itzchakov
  • 146,575
  • 32
  • 257
  • 321
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
0

you can try something like this

trait InputProcessor[S <: AnyInput, T <: Input[S#InType]] {
  implicit val evidence: T =:= S = implicitly[T =:= S]
}

and than the implementation would be:

class ImageProcessor extends InputProcessor[InpImage, InpImage] { }

you can read more about =:= here: https://stackoverflow.com/a/3427759/245024

EDIT: added an example and the implementation to the evidence
notice that when extending InputProcessor, if you pass 2 different type parameters, the code won't compile (as you would expect)

lev
  • 3,986
  • 4
  • 33
  • 46