I`m experimenting with Scala and slightly confused by type inference problem.
Given the definition below, which compiles successfully:
case class SequentialHistory[+E](events: Seq[E])
trait Event
case class SampleEvent(value: String) extends Event
def addEvent[E, E2 >: E](event: E)(history:SequentialHistory[E2]):
SequentialHistory[E2] = history.copy(events = event +: history.events)
I would like to understand why type inference not working properly and compilation of:
val hist = SequentialHistory(Seq.empty[Event])
//hist: SequentialHistory[Event] = SequentialHistory(List())
val histWithEvent = addEvent(SampleEvent("Does not compile"))(hist)
//error
result in compiler error:
Error:(21, 62) type mismatch;
found : SequentialHistory[Event]
required: SequentialHistory[SampleEvent]
addEvent(SampleEvent("Does not compile"))(hist)
^
but, if I swap parameter lists in addEvent
method definition:
def addEvent2[E, E2 >: E](history: SequentialHistory[E2])(event: E):
SequentialHistory[E2] = history.copy(events = event +: history.events)
that would solve the problem, types inferred correctly and snippet below compiles:
val hist2 = SequentialHistory(Seq.empty[Event])
//hist2: SequentialHistory[Event] = SequentialHistory(List())
val histWithEvent2 = addEvent2(hist)(SampleEvent("Compiles"))
//histWithEvent1: SequentialHistory[Event] =
// SequentialHistory(List(SampleEvent1(Compiles)))
Why Scala compiler can`t infer types correctly in first version of addEvent
?