I have the following code. The compiler complains about the last line. I am wondering why. The WrappedFunction
case class takes a function object with trait arguments. When I try to construct a WrappedFunction
object, I provide it with a function that has case classes that extend the trait as arguments. Intuitively this should work but for some reason it doesn't.
I have multiple functions, each combining two case classes and combining them into one. All of these, both argument types as well as the result types are subclasses of the trait Wrapped. I would like to have all these functions under one umbrella. Is it possible to do this in Scala? What's the best way to solve this?
trait Wrapped {
def name: String
}
case class WrappedInt1(i: Int) extends Wrapped {
override def name: String = "wrapped1"
}
case class WrappedInt2(i: Int) extends Wrapped {
override def name: String = "wrapped2"
}
case class WrappedInt3(i: Int) extends Wrapped {
override def name: String = "wrapped3"
}
case class WrappedFunction(function: (Wrapped, Wrapped) => Wrapped)
def plus(w1: WrappedInt1, w2: WrappedInt2): WrappedInt3 = WrappedInt3(w1.i + w2.i)
val f1 = WrappedFunction(plus)
Try to make WrappedFunction
generic:
case class WrappedFunction[W1 <: Wrapped, W2 <: Wrapped](function: (W1, W2) => Wrapped)
or
case class WrappedFunction[W1 <: Wrapped, W2 <: Wrapped, W3 <: Wrapped](function: (W1, W2) => W3)
or
case class WrappedFunction[-W1 <: Wrapped, -W2 <: Wrapped, +W3 <: Wrapped](function: (W1, W2) => W3)
Then your code compiles: https://scastie.scala-lang.org/DmytroMitin/ELIkgesXRNCmWNaflxFFpg/5
You can read about variances:
Variance in function types (Scala)
Subtyping between function types