Scala类型类隐式解析

亚历克斯·阿卜杜加法罗夫(Alex Abdugafarov)

(Scala 2.11.8)

考虑以下代码:

object ScalaTest extends App {
  class Wrapper {
    import Wrapper._

    def init(): Unit = {
      // "could not find implicit value for parameter tc: ScalaTest.Wrapper.TC[Int]"
      printWithTC(123)

      // Compiles
      printWithTC(123)(IntTC)

      // Compiles again!
      printWithTC(132)
    }
  }

  object Wrapper {
    trait TC[A] {
      def text(a: A): String
    }

    implicit object IntTC extends TC[Int] {
      override def text(a: Int) = s"int($a)"
    }

    def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = {
      println(tc.text(a))
    }
  }

  (new Wrapper).init()
}

我对这段代码有很多疑问:

  1. 为什么IntTC首先没有解决?
  2. 为什么一次使用后会编译?(如果您注释掉第一次调用,则代码有效)
  3. 应该在哪里放置typeclass隐式函数以正确解析?
贾斯珀

使用val具有明确的返回类型。参见https://github.com/scala/bug/issues/801https://github.com/scala/bug/issues/8697(以及其他)。
隐式对象与具有推断的返回类型的隐式val和def具有相同的问题。至于第二个问题:IntTC显式使用when时,您将强制编译器进行类型检查,因此在此之后,其类型是已知的,可以通过隐式搜索找到。

class Wrapper {
  import Wrapper._

  def init(): Unit = {
    // Compiles
    printWithTC(123)

    // Compiles
    printWithTC(123)(IntTC)

    // Compiles
    printWithTC(132)
  }
}

object Wrapper {
  trait TC[A] {
    def text(a: A): String
  }

  implicit val IntTC: TC[Int] = new TC[Int] {
    override def text(a: Int) = s"int($a)"
  }

  def printWithTC[A](a: A)(implicit tc: TC[A]): Unit = {
    println(tc.text(a))
  }
}

如果您确实希望隐式对象像对象一样被懒惰地求值,则可以使用implicit lazy val带有显式类型的。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章