2017-10-12 86 views
0

我已经在无形以下产品类型的实现:递归调用在哪里?

trait CsvEncoder[A] { 
    def encode(value: A): List[String] 
} 

implicit val hnilEncoder: CsvEncoder[HNil] = 
createEncoder(_ => Nil) 


implicit def hlistEncoder[H, T <: HList](
             implicit 
             hEncoder: CsvEncoder[H], 
             tEncoder: CsvEncoder[T] 
            ): CsvEncoder[H :: T] = 
createEncoder { 
    case h :: t => 
    hEncoder.encode(h) ++ tEncoder.encode(t) 
} 

,它是用来如下:

val reprEncoder: CsvEncoder[String :: Int :: Boolean :: HNil] = 
    implicitly 
println(reprEncoder.encode("abc" :: 123 :: true :: HNil)) 

在实例实施HList来看,我看不到递归调用的任何地方。因为HList就像一个列表,它应该递归处理,但我无法将其配置出去。

回答

3

它发生在tEncoder.encode(t)。尤其让我们分析下面的代码:

case h :: t => 
    hEncoder.encode(h) ++ tEncoder.encode(t) 

case h :: t解构其头和尾部分的HList。然后hEncoder.encode(h)H类型的值h转换为List[String]。之后tEncoder.encode(t)递归编码其余的HList,直到它到达基本情况,由HNil代表,其结果是Nil,即空的List。使用++连接中间结果,这是用于连接两个Scala List实例的运算符。