了解 "diverging implicit expansion"
Understanding "diverging implicit expansion"
Shapeless Guide 或多或少提供了以下代码。我将名称从 CsvEncoder
更改为 Foo
。
$cat build.sbt
scalaVersion := "2.12.1"
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.3.2"
)
和
$cat src/main/scala/net/Foo.scala
package net
import shapeless.{::, Generic, HList, HNil, Lazy}
object Foo {
def apply[A](implicit ev: Foo[A]): Foo[A] = ev
def instance[A](f: A => List[String]): Foo[A] =
new Foo[A] {
override def encode(x: A): List[String] = f(x)
}
implicit val hnilEncoder: Foo[HNil] =
instance[HNil](hnil => Nil)
implicit def hlistEncoder[H, T <: HList](
implicit hEncoder: Foo[H],
tEncoder: Foo[T]
): Foo[H :: T] =
instance[H :: T] {
case h :: t => hEncoder.encode(h) ++ tEncoder.encode(t)
}
implicit def genericEncoder[A, R](
implicit gen: Generic[A] { type Repr = R },
enc: Foo[R]): Foo[A] =
instance[A] { a =>
enc.encode( gen.to(a) )
}
}
case class Bar(baz: Int, qux: String)
case class Bippy(bar: Bar)
trait Foo[A] {
def encode(x: A): List[String]
}
然后我尝试解析一个隐含的 Foo[Bippy]
:
> console
[info] Starting scala interpreter...
[info]
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.
scala> import net.Foo
import net.Foo
scala> import net._
import net._
scala> implicitly[Foo[Bippy]]
<console>:16: error: diverging implicit expansion for type net.Foo[net.Bippy]
starting with method genericEncoder in object Foo
implicitly[Foo[Bippy]]
^
文本指出在编译时失败之前发生了以下解决步骤:
Foo[Bippy] // 1
Foo[Bar :: HNil] // 2
Foo[Bar] // 3
Foo[Int :: String :: HNil] // 4 uh oh
但是,2->3的转换我不明白,请解释。
第 2 步是 genericEncoder[Bippy, Bar :: HNil]
中的 enc: Foo[R]
。
要解决它会查看 hlistEncoder[Bar, HNil]
,这需要 hEncoder: Foo[Bar]
,这是第 3 步。
Shapeless Guide 或多或少提供了以下代码。我将名称从 CsvEncoder
更改为 Foo
。
$cat build.sbt
scalaVersion := "2.12.1"
libraryDependencies ++= Seq(
"com.chuusai" %% "shapeless" % "2.3.2"
)
和
$cat src/main/scala/net/Foo.scala
package net
import shapeless.{::, Generic, HList, HNil, Lazy}
object Foo {
def apply[A](implicit ev: Foo[A]): Foo[A] = ev
def instance[A](f: A => List[String]): Foo[A] =
new Foo[A] {
override def encode(x: A): List[String] = f(x)
}
implicit val hnilEncoder: Foo[HNil] =
instance[HNil](hnil => Nil)
implicit def hlistEncoder[H, T <: HList](
implicit hEncoder: Foo[H],
tEncoder: Foo[T]
): Foo[H :: T] =
instance[H :: T] {
case h :: t => hEncoder.encode(h) ++ tEncoder.encode(t)
}
implicit def genericEncoder[A, R](
implicit gen: Generic[A] { type Repr = R },
enc: Foo[R]): Foo[A] =
instance[A] { a =>
enc.encode( gen.to(a) )
}
}
case class Bar(baz: Int, qux: String)
case class Bippy(bar: Bar)
trait Foo[A] {
def encode(x: A): List[String]
}
然后我尝试解析一个隐含的 Foo[Bippy]
:
> console
[info] Starting scala interpreter...
[info]
Welcome to Scala 2.12.1 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_112).
Type in expressions for evaluation. Or try :help.
scala> import net.Foo
import net.Foo
scala> import net._
import net._
scala> implicitly[Foo[Bippy]]
<console>:16: error: diverging implicit expansion for type net.Foo[net.Bippy]
starting with method genericEncoder in object Foo
implicitly[Foo[Bippy]]
^
文本指出在编译时失败之前发生了以下解决步骤:
Foo[Bippy] // 1
Foo[Bar :: HNil] // 2
Foo[Bar] // 3
Foo[Int :: String :: HNil] // 4 uh oh
但是,2->3的转换我不明白,请解释。
第 2 步是 genericEncoder[Bippy, Bar :: HNil]
中的 enc: Foo[R]
。
要解决它会查看 hlistEncoder[Bar, HNil]
,这需要 hEncoder: Foo[Bar]
,这是第 3 步。