Shapeless' 懒惰和隐式参数

问题描述

我正在尝试跟踪构造序列(大量 println)并拥有此代码 https://scastie.scala-lang.org/4DRXuhUZS8mN551eI7vN3Q

<item name="primaryTextColorDefault">

当我运行它时,它会打印出来

import shapeless._
object abc {
  sealed trait List[+T]
  case class Cons[T](hd: T,tl: List[T]) extends List[T]
  sealed trait Nil extends List[nothing]
  case object Nil extends Nil

  trait Show[T] {
    def apply(t: T): String
  }

  object Show {
    // Base case for Int
    implicit def showInt: Show[Int] = new Show[Int] {
      println("222")
      def apply(t: Int) = t.toString
      println("222 end")
    }
    // Base case for Nil
    implicit def showNil: Show[Nil] = new Show[Nil] {
      def apply(t: Nil) = "Nil"
    }
    
    // without Lazy,resoving sc requires resolving sl,which in turn sc -- infinite looping
    // Lazy stops this looping and saying I got this,so go on to resolve showCons using proxy st and sl. real st and sl can be accessed using st.value and sl.value
    // which will lazily resolved.
    // Case for Cons[T]: note (mutually) recursive implicit argument referencing Show[List[T]]
    implicit def showCons[T](implicit st: Lazy[Show[T]],sl: Lazy[Show[List[T]]]): Show[Cons[T]] = { 
      val t = new Show[Cons[T]] {
      println(" 111")
      def apply(t: Cons[T]) = {
          println("     apply 111 ")
          println(s"      try to show ${t.tl}")
          val sss = s"Cons(${show(t.hd)(st.value)},${show(t.tl)(sl.value)})"
          println("     apply 111 end ")
          sss
      }
      println(" 111 end") // the reason 111 comes before 333 at the beginning is determined by internal algorithm of Lazy
      }
      t
    }
    // Case for List[T]: note (mutually) recursive implicit argument referencing Show[Cons[T]]
    implicit def showList[T](implicit sc: Lazy[Show[Cons[T]]]): Show[List[T]] = new Show[List[T]] {
      println(" 333")
      def apply(t: List[T]) = t match {
        case n: Nil => show(n)
        case c: Cons[T] => { 
          println("  apply 333")
          val tmp = show(c)(sc.value) //explicitly passing down parameter
          println("  apply 333 end") 
          tmp
        }
      }
      println(" 333 end")
    }
  }

  def show[T](t: T)(implicit s: Show[T]) = s(t)
  def main(args: Array[String]): Unit = {
    val l: List[Int] = Cons(1,Cons(2,Cons(3,Nil)))
    println(show(l))
  }
}

为什么 111 111 end 333 333 end apply 333 apply 111 try to show Cons(2,Nil)) 222 222 end 333 333 end apply 333 apply 111 try to show Cons(3,Nil) apply 333 apply 111 try to show Nil apply 111 end apply 333 end apply 111 end apply 333 end apply 111 end apply 333 end Cons(1,Nil))) 111111 end333 之前被执行(构造),即使 333 end 中包含 implicit sc: Lazy[Show[Cons[T]]]?不应该延迟到 Lazy 被引用吗? 我可以看到 sc.valuest 是惰性构造的,但是想知道为什么 sl 是立即构造的? Lazy 算法是否认为构造 sc 不会导致无限循环问题?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)