スカラ標準ライブラリのみを使用する場合は、Numeric[T]
をご覧ください。あなたの場合、非整数除算を行うため、Numeric
のサブクラスFractional[T]
を使用する必要があります。
スカラー標準ライブラリの型式を使用してコードを表示する方法を示します。 Fractional
はOrdered
から続きます。この場合は便利ですが、数学的には一般的ではありません。例えば。注文されていないためComplex
にFractional[T]
を定義することはできません。
def bucketiseScala[T: Fractional](buckets: Seq[T], candidate: T): T = {
// so we can use integral operators such as + and/
import Fractional.Implicits._
// so we can use ordering operators such as <. We do have a Ordering[T]
// typeclass instance because Fractional extends Ordered
import Ordering.Implicits._
// integral does not provide a simple way to create an integral from an
// integer, so this ugly hack
val two = (implicitly[Fractional[T]].one + implicitly[Fractional[T]].one)
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y)/two
if (candidate < midPoint) x else y
}
}
しかし、深刻な一般的な数値計算のために私はspire見てみることをお勧め。はるかに精巧な数値型の階層構造を提供します。 Spireのタイプメーターも特殊化されているため、プリミティブを直接使用するほど高速に動作します。ここで
は尖塔を使用して見えるの例を使用する方法である:
// imports all operator syntax as well as standard typeclass instances
import spire.implicits._
// we need to provide Order explicitly, since not all fields have an order.
// E.g. you can define a Field[Complex] even though complex numbers do not
// have an order.
def bucketiseSpire[T: Field: Order](buckets: Seq[T], candidate: T): T = {
// spire provides a way to get the typeclass instance using the type
// (standard practice in all libraries that use typeclasses extensively)
// the line below is equivalent to implicitly[Field[T]].fromInt(2)
// it also provides a simple way to convert from an integer
// operators are all enabled using the spire.implicits._ import
val two = Field[T].fromInt(2)
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y)/two
if (candidate < midPoint) x else y
}
}
Field[T]
が存在する場合スパイアもT
の整数から自動変換を提供しますので、あなたもほぼ同じ(このように例を書くことができます非ジェネリック版)。しかし、私は上記の例が理解しやすいと思う。
// this is how it would look when using all advanced features of spire
def bucketiseSpireShort[T: Field: Order](buckets: Seq[T], candidate: T): T = {
buckets.foldLeft(buckets.head) { (x, y) =>
val midPoint = (x + y)/2
if (candidate < midPoint) x else y
}
}
更新:spireは非常に強力で一般的ですが、やや初心者に混乱することもあります。特に物事がうまくいかないとき。基本的なアプローチといくつかの問題を説明するexcellent blog postがあります。
ありがとう、私は尖塔をチェックします。 Int(http://www.scala-lang.org/api/current/index.html#scala.Int)のscalaドキュメントが拡張された特性をリストしていないので、 'Ordering '。 'Int'がどのような特徴を持ち、数値型のものが見つかったのか、どうすればわかりますか? – jbrown
@jbrown注文は[typeclass]です(http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html)。タイプメーターは継承を使用して動作しません。 –
どのように知っていたのですか? – jbrown