2013-05-13 6 views
8

私は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] = [email protected] 
scala> p1 eval 3 
<console>:9: error: could not find implicit value for parameter r: p1.Semiring[Int] 
       p1 eval 3 
       ^

私はそれを修正する方法がわかりません。暗黙のオブジェクトを間違った場所に定義していますか?クラス外に移動しようとしましたが、コンパイラが失敗します。それが正しく動作するためには何か必要なことはありますか?

+0

あなたはあまりにもスパイアで見たいと思うかもしれません:https://github.com/non/spireを:「スパイアがあることを意図しているScalaのための数値ライブラリですジェネリック、高速、正確。 Spireは、スペシャライゼーション、マクロ、タイプクラス、インプリシットなどの機能を使用して、パフォーマンスと精度のトレードオフを回避する従来の知恵を無視します。主要な目標は、開発者が特定の数値表現を「焼く」ことなく効率的な数値コードを書くことができるようにすることです。ほとんどの場合、Spireの特殊な型クラスを使用する一般的な実装は、対応する直接実装と同じように機能します。 " –

答えて

15

暗黙の解決は、関数を呼び出す場所で行われ、定義する場所では行われません。あなたはp1.evalを呼び出す前に、あなたの暗黙をインポートする必要があります。

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

あなたの暗黙のは本当にポリのインスタンスにバインドされていないので、あなたはポリ外でそれらを定義することができます。

明示的Semiring暗黙をインポートしたくない場合は、あなたは彼らが欠落しているとき、コンパニオンオブジェクトに暗黙のマッチングのためのScala検索以来Semiringのコンパニオンオブジェクトでそれらを定義することができます。

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 
+0

私は明示的にimport p1._を呼び出さなくても自動的にそれを得る方法はありますか? – Joe

+0

編集を参照私の答えのバージョン:) –

+0

ありがとう、それはトリックを完了しました。 – Joe

関連する問題