2017-01-05 7 views
1

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. Пожалуйста, объясните.

+1

На общей ноте, что позволяет '-Xlog-implicits' ** и ** с помощью https://github.com/ tek/splain помогает понять неявные проблемы. – Haspemulator

ответ

1

Этап 2 является enc: Foo[R] в genericEncoder[Bippy, Bar :: HNil].

Чтобы решить, что он смотрит на hlistEncoder[Bar, HNil] который требует hEncoder: Foo[Bar], что шаг 3.

Смежные вопросы