2013-05-13 11 views
8

Próbuję napisać kod reprezentujący wielomiany w Scali. Potrzebuję tego kodu, aby był polimorficzny, więc używam implicite do radzenia sobie z różnymi typami. Mam:Używanie niejawnych obiektów w klasach

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] = ... 
} 

W tym miejscu wycięłam kilka funkcji dla zwięzłości. Kompiluje się to dobrze, ale kiedy próbuję go użyć, dostaję dziwne błędy:

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

Nie jestem pewien, jak to naprawić. Czy definiuję ukryte obiekty w niewłaściwym miejscu? Próbowałem przenieść je poza klasę, ale kompilator zawodzi. Czy jest coś jeszcze, co muszę zrobić, aby działało prawidłowo?

+0

Możecie zajrzeć do Iglicy też: https://github.com/non/spire: „Spire jest biblioteką numeryczną do Scala, który ma być generyczny, szybki i precyzyjny Korzystając z takich funkcji, jak specjalizacja, makra, klasy typów i implikacje, Spire ciężko pracuje, aby przeciwstawić się konwencjonalnej mądrości dotyczącej wydajności i precyzyjnych kompromisów. Głównym celem jest umożliwienie programistom pisania efektywnego kodu numerycznego bez konieczności "upieczania" poszczególnych reprezentacji numerycznych. W większości przypadków ogólne implementacje używające wyspecjalizowanych klas Spire'a zachowują się identycznie z odpowiednimi implementacjami bezpośrednimi. " –

Odpowiedz

15

Niejawna rozdzielczość jest wykonywana w miejscu, w którym wywołuje się funkcję, a nie w miejscu jej zdefiniowania. Należy zaimportować implicits przed wywołaniem p1.eval:

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

Ponieważ twoi implicits naprawdę nie są zobowiązane do wystąpienia Poly, można określić je na zewnątrz Poly.

Jeśli nie chcesz importować bezpośrednio z Semiring implicits, można je zdefiniować w obiekcie towarzysz Semiring od poszukiwania Scala dopasowywania implicits w obiekcie towarzysz gdy brakuje:

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

Następnie nie trzeba importować je już:

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

Rozumiem. Czy jest jakiś sposób, aby to się stało automatycznie, bez konieczności jawnego wywoływania importu p1._? – Joe

+0

Zobacz edytowane wersja mojej odpowiedzi :) –

+0

Dzięki, to się udało. – Joe

Powiązane problemy