В следующем блоке кода (и с scala 2.11
, и с 2.12
) метод apply
не компилируется, а applyInlined
-.
package blar
trait Bar[T]
class A
class B
class C
trait Exploder[T] {
// Removing explode and changing Foo so that
// flatMap takes no param means it will compile
def explode(product: C): Seq[T]
val bar: Bar[T]
}
case object Exploder1 extends Exploder[A] {
def explode(product: C): Seq[A] = ???
val bar: Bar[A] = ???
}
case object Exploder2 extends Exploder[B] {
def explode(product: C): Seq[B] = ???
val bar: Bar[B] = ???
}
object Thing {
def apply(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
wrapped(exploder)
}
def applyInlined(): Unit = List(Exploder1, Exploder2).foreach {
case exploder: Exploder[_] =>
flatMap(exploder.explode)(exploder.bar)
}
def flatMap[U: Bar](explode: C => TraversableOnce[U]): Unit = ???
def wrapped[T](exploder: Exploder[T]): Unit =
flatMap(exploder.explode)(exploder.bar)
}
Сообщение об ошибке
[error] .../src/main/scala/blar/Bar.scala:34:42: type mismatch;
[error] found : blar.Bar[_1]
[error] required: blar.Bar[Object]
[error] Note: _1 <: Object, but trait Bar is invariant in type T.
[error] You may wish to define T as +T instead. (SLS 4.5)
[error] flatMap(exploder.explode)(exploder.bar)
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed 03-Jan-2019 13:43:45
- Мой главный вопрос: почему?Это ошибка?
Как видите, applyInlined
отличается только тем, что содержит тело метода wrapped
.Это означает, что каким-то образом дополнительная упаковка некоторого кода в методе «обманула» компилятор в работу.
Другой вопрос: можете ли вы вспомнить дизайн / хак, который бы избегал такого рода вещей без , делающего Blar
ковариантным?Как я могу заставить встроенную версию скомпилировать?Могу ли я сделать это с asInstanceOf
Что такое scala, выводящая тип, для вызова wrapped
без явного параметра типа?