在类中使用隐式对象 [英] Using implicit objects within classes

查看:40
本文介绍了在类中使用隐式对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试编写代码以表示Scala中的多项式.我需要将此代码设置为多态类型,因此我正在使用隐式来处理不同的类型.我有:

I am trying to write code to represent polynomials within Scala. I need this code to be type polymorphic, so I am using implicits to deal with different types. I have:

case class Mono[T](degree: Int, coeff: T) {
  def Degree: Int = return degree
  def Coeff: T = return coeff
}

class Poly[T](private val terms: List[Mono[T]]) {

  trait Semiring[T] {
    def add(x:T, y:T): T
    def mul(x:T, y:T): T
    def exponent(x: T, n:Int): T
    val unitA: T
  }

  implicit object IntSemiring extends Semiring[Int] {
    def add(x: Int, y: Int): Int = x+y
    def mul(x: Int, y: Int): Int = x*y
    def exponent(x: Int, n:Int): Int = if(n==0) 1 else x*exponent(x, n-1)
    val unitA: Int = 0
  }

  implicit object SetSemiring extends Semiring[Set[Int]] {
    def add(x: Set[Int], y: Set[Int]): Set[Int] = x.union(y)
    def mul(x: Set[Int], y: Set[Int]): Set[Int] = x.intersect(y)
    def exponent(x: Set[Int], n: Int): Set[Int] = x
    val unitA: Set[Int] = Set()
  }

  def eval(x: T)(implicit r: Semiring[T]): T = {
    var termlist = terms
    var sum = r.unitA
    var expression = terms
    while(!termlist.isEmpty) {
      val term = expression.head
      val power = r.exponent(x, term.Degree)
      val termval = r.mul(power, term.Coeff)
      sum = r.add(sum, termval)
      termlist = termlist.tail
    }
    return sum
  }      

  def add(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...

  def mul(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
}

为了简洁起见,我砍掉了一些功能.可以很好地编译,但是当我尝试使用它时,会遇到一些奇怪的错误:

I chopped out a few functions for brevity there. This compiles fine but when I try and use it I get some strange errors:

scala> val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1: Poly[Int] = Poly@450ae3fb
scala> p1 eval 3
<console>:9: error: could not find implicit value for parameter r: p1.Semiring[Int]
              p1 eval 3
                 ^

我不确定该如何解决.我是否在错误的位置定义了隐式对象?我试图将它们移出课堂,但编译器失败了.我还需要做其他事情才能使其正常工作吗?

I'm not sure how to fix it. Am I defining the implicit objects in the wrong place? I tried moving them outside the class but then the complier fails. Is there something else I need to do to get it to work properly?

推荐答案

隐式解析是在调用函数的位置而不是在定义函数的位置进行的.您应该在调用 p1.eval 之前导入您的隐式对象:

Implicit resolution is done at the location where you call the function, not where you define it. You should import your implicits before calling p1.eval:

val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
import p1._
p1 eval 3

由于隐式对象并未真正绑定到Poly实例,因此可以在Poly之外定义它们.

Since your implicits are not really bound to an instance of Poly, you can define them outside Poly.

如果您不想显式导入 Semiring 隐式,则可以在 Semiring 的伴随对象中定义它们,因为Scala在伴随对象中搜索匹配的隐式当他们失踪时:

If you don't want to import explicitly the Semiring implicits, you can define them in the companion object of Semiring since Scala search for matching implicits in the companion object when they are missing:

case class Mono[T](degree: Int, coeff: T) {
  def Degree: Int = return degree
  def Coeff: T = return coeff
}

class Poly[T](private val terms: List[Mono[T]]) {
  def add(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...

  def mul(that: Poly[T])(implicit r: Semiring[T]): Poly[T] = ...
}

trait Semiring {
    def add(x:T, y:T): T
    def mul(x:T, y:T): T
    def exponent(x: T, n:Int): T
    val unitA: T
}

object Semiring {
  implicit object IntSemiring extends Semiring[Int] {
    def add(x: Int, y: Int): Int = x+y
    def mul(x: Int, y: Int): Int = x*y
    def exponent(x: Int, n:Int): Int = if(n==0) 1 else x*exponent(x, n-1)
    val unitA: Int = 0
  }

  implicit object SetSemiring extends Semiring[Set[Int]] {
    def add(x: Set[Int], y: Set[Int]): Set[Int] = x.union(y)
    def mul(x: Set[Int], y: Set[Int]): Set[Int] = x.intersect(y)
    def exponent(x: Set[Int], n: Int): Set[Int] = x
    val unitA: Set[Int] = Set()
  }
}

那么您就不再需要导入它们了:

Then you don't need to import them anymore:

val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1 eval 3

这篇关于在类中使用隐式对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆