I have defined a trait Mergeable that represents a value that can be merged with another of its kind, but I'm having trouble declaring the types correctly.
trait Mergeable[T] {
def value: Option[T]
def merge(other: ???): ???
}
trait SummingInt extends Mergeable[Int] {
def merge(other: SummingInt): SummingInt = {
val sum = for {
i1 <- value
i2 <- other.value
} yield i1 + i2
sum orElse this orElse other
}
}
trait MultiplyingInt extends Mergeable[Int] {
def merge(other: MultiplyingInt): MultiplyingInt = {
val product = for {
i1 <- value
i2 <- other.value
} yield i1 * i2
product orElse this orElse other
}
}
I want to require that all Mergeable define a method merge that merges it with another of it's own kind. So it is illegal to merge a SummingInt with a MultiplyingInt.
If I choose:
def merge(other: Mergeable[T]): Mergeable[T]
Then I lose that guarantee of only merging like-with-like. But if I don't define merge on Mergeable, then I cannot write this method which would make my life a whole lot simpler:
def mergeTwo[T <: Mergeable](first: T, second: T) = first merge second
Even though mergeTwo can guarantee that first and second are of the same type and thus are safe to merge!
Does the Scala language make it at all possible for me to define merge at the level of Mergeable?