了解 "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 步。