繁体   English   中英

Scala类型类隐式解析

[英]Scala typeclasses implicit resolution

(斯卡拉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. 为什么IntTCIntTC得到解决?
  2. 为什么它在使用一次后编译? (如果您注释掉第一次调用,代码可以正常工作)
  3. 应该在哪里设置类型隐含以便正确解决?

使用具有显式返回类型的val 请参阅https://github.com/scala/bug/issues/801https://github.com/scala/bug/issues/8697 (以及其他内容)。
隐式对象与隐式val和defs具有相同的问题,具有推断的返回类型。 至于你的第二个问题:当显式使用IntTC时,你强制编译器对它进行类型检查,所以在那之后它的类型是已知的并且可以通过隐式搜索找到。

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地对你的隐式进行求值,你可以使用带有显式类型的implicit lazy val

在使用之前定义隐式。

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))
  }
}

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)
  }
}

(new Wrapper).init()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM