Ordering[T]型クラスを暗黙のパラメーターとして使用できます。一般的な max 関数を書きたい場合は、次のようになります。
def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = {
if(ordering.gt(a,b)) a else b
}
Int、Float などのプリミティブ データ型の場合、暗黙の Ordering[T] がスコープ内にあるため、期待どおりに使用できます。
max(1,2) // gives 2
Ordered[T] を実装するすべての型には、Ordering[T] を提供するための暗黙的なものもあります。
順序付けを組み合わせるさまざまなメソッドもスコープ内にあります。たとえば、各要素に Ordering[T] がある N タプルがある場合、タプル タイプの Ordering が自動的に存在します。
max((1,2), (3,4)) // gives (3,4) because 3 is larger than 1
しかし、暗黙的に提供された順序付けのいずれにも満足できない場合は、独自の順序付けを作成して明示的に渡すか、スコープ内で暗黙的な val として取得することもできます。このような:
val negativeIntOrdering = new Ordering[Int] {
def compare(a:Int,b:Int) = b - a
}
max(1,2)(negativeIntOrdering) // gives 1
したがって、型クラス ベースのアプローチは、継承ベースのアプローチよりもはるかに柔軟です。これが、 spireのような数学ライブラリが広く使用する理由です。
上記のコードが良くない点の 1 つは、演算子の代わりに lt メソッドを使用する必要があることです。しかし、それにも解決策があります。Ordering には、T の演算子を提供する mkOrderingOps という暗黙のメソッドがあります。次のように、ordering._ をインポートしてスコープ内で取得する必要があります。
def max[T](a:T, b:T)(implicit ordering:Ordering[T]) = {
import ordering._;
if(a>b) a else b
}