I次のコードを持っています。エラーとインポート暗黙
case class Custom(value: Int)
case class Custom2(value: Float)
case class MappedEncoding[I, O](f: I => O)
trait Decoders {
type BaseDecoder[T] =() => T
type Decoder[T] <: BaseDecoder[T]
}
trait ConcreteDecoders extends Decoders {
type Decoder[T] = ConcreteDecoder[T]
case class ConcreteDecoder[T](decoder:() => T) extends BaseDecoder[T] {
def apply(): T = decoder()
}
implicit def optionDecoder[T](implicit d: Decoder[T]): Decoder[Option[T]] =
ConcreteDecoder[Option[T]](() => Some(d()))
implicit def mappedDecoder[I, O](implicit mapped: MappedEncoding[I, O], decoder: Decoder[I]): Decoder[O] =
ConcreteDecoder[O](() => mapped.f(decoder()))
implicit def intDecoder: Decoder[Int] = ConcreteDecoder[Int](() => 1)
implicit def floatDecoder: Decoder[Float] = ConcreteDecoder(() => 1)
}
class ConcreteContext extends ConcreteDecoders {
}
case class TestObject() {
implicit val customDecoder = MappedEncoding[Int, Custom](Custom)
implicit val custom2Encoder = MappedEncoding[Custom2, Float](_.value) // 1
implicit val custom2Decoder = MappedEncoding[Float, Custom2](Custom2)
def a(c: ConcreteContext): Unit = {
import c._
implicitly[Decoder[Option[Custom]]] // 2
// implicitly[Decoder[Float]] // 3
implicitly[Decoder[Option[Float]]]
()
}
}
object Main extends App {
implicit val c = new ConcreteContext()
TestObject().a(c)
// TestObject(a).()
}
そして、それはScalaの2.11.8でコンパイルしないと2.12.0:
diverging implicit expansion for type c.Decoder[Option[Float]]
[error] starting with method intDecoder in trait ConcreteDecoders
[error] implicitly[Decoder[Option[Float]]]
を
-Xlog-implicits
オプションを使用すると、長い出力を与えるが、最も興味深い部分がある:
floatDecoder is not a valid implicit value for c.Decoder[Float] because:
[info] diverging implicit expansion for type c.Decoder[T]
[info] starting with method intDecoder in trait ConcreteDecoders
[info] implicitly[Decoder[Option[Float]]]
methodパラメーターからcaseクラスのコンストラクターパラメーターにc: CustomContext
を移動すると、コンパイルされます。私はそれが検索範囲を暗黙に変更するかもしれないと思った。また
次のいずれかの操作は、それをコンパイルします:
- コメント
1
(==ライン1)でマークされた行をコメント - コメント行2
- コメントを解除行3
implicitly[Decoder[Option[Float]]]
の解決に影響する状態で、implicitly[Decoder[Option[Custom]]]
がScalaコンパイラを終了させるように見えます。
どうしてこのようなことが起こっていて、メソッドパラメータからc: ConcreteContext
を移動せずにコンパイルするにはどうすればよいですか?
P.S.これは問題を再現する簡単なコードです。実際のコードははるかに複雑で、ConcreteContext
がメソッドパラメータとして渡されたときにサポートする必要があります。
を作るためにあなたの
としてmappedDecoder
を書き換えることができます。これは[SI-9625](https://issues.scala-lang.org/browse/SI-9625)と多少関連しているようです。この問題は、メソッドのparamをコンストラクタparamに変換すると消えます。 sidenoteでは、 'Decoder'を' Function0'のサブタイプにすることは最善の考えではないかもしれません。 –
@ Jasper-M http://stackoverflow.com/q/40391732/746347のため、 'Decoder'を' Function0'のサブタイプにしました。 – mixel
明らかな回避策 'val c0:c.type = c; import c0._' def a(c:ConcreteContext):Unit'はあなたのニーズに十分ですか? –