我有以下代碼:進口implicits作爲方法參數傳遞VS類的構造函數參數
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).()
}
而且它不會在斯卡拉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]]]
將c: CustomContext
從方法參數移動到case類構造函數參數使其編譯。我認爲這可能會改變暗示搜索範圍。
此外下列動作中的一個使其編譯:
- 評論線標有註解
1
(==第1行) - 註釋線2
- 取消註釋線3
它看起來像解決implicitly[Decoder[Option[Custom]]]
葉斯卡拉編譯器處於影響解決implicitly[Decoder[Option[Float]]]
的狀態。
爲什麼會發生這種情況,如何在不移動c: ConcreteContext
的方法參數的情況下編譯它?
P.S.這是重現問題的簡化代碼。真正的代碼要複雜得多,我需要支持ConcreteContext
作爲方法參數傳遞的情況。
的東西在這裏肯定有鬼。這似乎與[SI-9625](https://issues.scala-lang.org/browse/SI-9625)有些相關。將方法參數變爲構造函數參數時,該問題也會消失。在旁註中,將'Decoder'作爲'Function0'的子類型可能也不是最好的想法。 –
@ Jasper-M由於http://stackoverflow.com/q/40391732/746347,我使'Decoder'成爲'Function0'的一個子類型。 – mixel
顯而易見的解決方法'val c0:c.type = c;在def a(c:ConcreteContext):Unit'裏面導入c0._'就足夠滿足你的需求了? –