2012-01-14 4 views
9

簡単な例で説明するのは簡単だと思います。スカラ:特定のメソッドを実装するジェネリッククラスを指定することは可能ですか?

squaredメソッドを実装し、implicit defを使用して、*オペレータをサポートする任意のクラスに自動的に追加したいと思います。 intであり

それは非常に簡単です:

class EnhancedInt(x: Int) { def squared = x * x } 

implicit def IntToEnchancedInt(x: Int) = new EnhancedInt(x) 

しかし、どれかAnyValと、私は次のエラーを取得する:

scala> class EnhanceAny(x: AnyVal) { def squared = x * x } 
<console>:7: error: value * is not a member of AnyVal 
     class EnhanceAny(x: AnyVal) { def squared = x * x } 

私は任意の数値に適用できるか知りたいですクラス、またはさらには、*オペレータをサポートする任意のクラスに適用できます。

+0

+1良い質問です。これは私が問題を抱えているScalaのものです。ハスケルではghciで ':t \ x - > x * x'を使うだけです(それは' Num a => a - > a'です)。しかし、Scalaでは 'x => x * x'をREPLで実行すると、 '' x''型を与えていないことが分かります。そして、私は手を振って、Scalaの型システムがHaskellのものよりも "強力"であることを思い出させます。 –

+0

AnyValではなくNumericで動作する可能性があります。 Seq.product()が乗算へのアクセスをどのように管理しているかを見てください。 – scand1sk

+0

@ダンバートン:質問を正しく解釈していない可能性があります。下のDan Simonの答えを見てください。 – missingfaktor

答えて

8

それはあなたがに対処したい種類ごとに定型変換を記述することなく*方法であらゆる種類に機能するソリューションを持ってすることはできません。本質的には、再帰的な構造型が必要であり、ScalaはJVMの型削除のためにそれらをサポートしていません。詳細はpostを参照してください。

タイプクラスを使用して、タイプクラスとthisの質問に答えて、Numericタイプのクラスを使用して、あなたが望むものにかなり近づけることができます。これはほとんどのプリミティブで動作します:

//define the type class 
trait Multipliable[X] { def *(x: X): X} 

//define an implicit from A <% Numeric[A] -> Multipliable[Numeric[A]] 
implicit def Numeric2Mult[A](a: A)(implicit num: Numeric[A]): Multipliable[A] = new Multipliable[A]{def *(b: A) = num.times(a, b)} 

//now define your Enhanced class using the type class 
class EnhancedMultipliable[T <% Multipliable[T]](x: T){ def squared = x * x} 

//lastly define the conversion to the enhanced class 
implicit def Mult2EnhancedMult[T <% Multipliable[T]](x: T) = new EnhancedMultipliable[T](x) 

3.squared 
//Int = 9 

3.1415F.squared 
//Float = 9.869022 

123456789L.squared 
//Long = 15241578750190521 
+0

グレート、私はそれを試して、それが動作するので、私は正しい答えとしてマーク...しかし、私は行方不明のいくつかのことがあります...あなたはすべての数値クラスの "*"演算子をオーバーライドしていますか? ? – opensas

+1

並べ替え、オーバーライドするのではなく、インターフェイスの実装を提供するだけです。 'Multipliable'特性は、何らかの乗法概念を持つ型を表すものとします。数値型の場合、基本的にはこの乗算は実際の「通常の」乗算でなければなりませんが、別の方法で定義することもできます。 '3 * 3'は' Int'で定義された '*'を引き続き使用します –

0

考えてみましょう。掛け算は異なるオブジェクトで異なるプロパティを持っています。たとえば、整数乗算は連想であり、可換であり、スカラー倍算は可換性ではありません。浮動小数点数の乗算... しかし、もちろん、あなたは特性で、または型クラスに似た "形質と暗黙の"構造を持つことができます。

関連する問題