我正在尝试编写代码来表示Scala中的多项式。我需要这个代码是类型多态,所以我使用implicits来处理不同的类型。我有:
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] = ...
}
为了简洁起见,我删除了一些功能。编译很好,但是当我尝试使用它时,我会遇到一些奇怪的错误:
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
^
我不确定如何修复它。我在错误的地方定义了隐含的对象吗?我尝试将它们移到课堂外但是编译器失败了。为了让它正常工作,我还需要做些什么吗?
答案 0 :(得分:16)
隐式解析是在您调用函数的位置完成的,而不是您定义它的位置。您应该在致电p1.eval
之前导入您的含义:
val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
import p1._
p1 eval 3
由于你的implicits并没有真正绑定到Poly的实例,你可以在Poly。
之外定义它们如果您不想明确导入Semiring
隐含,则可以在Semiring
的配套对象中定义它们,因为Scala会在失踪时检索匹配对象中的匹配含义:
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()
}
}
然后你不再需要导入它们了:
val p1 = new Poly(List(Mono(0,1),Mono(1,2),Mono(2,1)))
p1 eval 3