Scala类型类隐式解析

时间:2017-05-31 10:19:48

标签: scala typeclass implicit

(Scala 2.11.8)

请考虑以下代码:

$text = '
<p>Author</p>
<p>Availability</p>
BeautyBeauty11055981
<p><a href="APPNDX_SortValuesArticle.html#salesrank">salesrank</a></p>BooksBooks1000';

if (preg_match_all('/[A-Za-z]+[\d]+/', $text, $matches)) {
    print_r($matches[0]); // Returns: Array ( [0] => BeautyBeauty11055981 [1] => BooksBooks1000 )
}

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

  1. 为什么不首先解决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() }
  2. 为什么在使用一次后编译? (如果您注释掉第一次调用,代码可以正常工作)
  3. 应该在哪里放置类型类暗示才能正确解决?

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

在使用之前定义隐式。

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