4

次のコード ブロック (scala2.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
  1. 私の主な質問は、なぜですか?これはバグですか?

ご覧のとおり、メソッドapplyInlinedの本体がインライン化されているという点だけが異なります。wrappedこれは、メソッド内の一部のコードの余分なラップが何らかの形でコンパイラを「だまして」動作させたことを意味します。

  1. もう1つの質問は、共変にせにこの種のことを回避する設計/ハックを考えてもらえBlarますか? インライン バージョンをコンパイルするにはどうすればよいですか? でできますかasInstanceOf

  2. wrapped明示的な型パラメーターなしで呼び出すために型を推測するscalaは何ですか?

4

1 に答える 1