理解"分歧隐含扩张"

时间:2017-01-05 02:48:12

标签: scala implicit

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转换到&gt;请解释一下。

1 个答案:

答案 0 :(得分:1)

第2步是enc: Foo[R]中的genericEncoder[Bippy, Bar :: HNil]

要解决此问题,请查看需要hlistEncoder[Bar, HNil]的{​​{1}},即第3步。