2015-10-12 14 views
5

I thought Tüm Ordering[_] türlerindeki işlevlerimi parametrelendirmem gerekiyor. Ama bu işe yaramıyor.Scala'daki tüm numaralar arasında bir işlev nasıl tanımlanır?

Gerekli matematiksel işlemleri destekleyen tüm türler için aşağıdaki işlevi nasıl çalıştırabilirim ve bunu kendi başıma nasıl bulabilirim?

/** 
    * Given a list of positive values and a candidate value, round the candidate value 
    * to the nearest value in the list of buckets. 
    * 
    * @param buckets 
    * @param candidate 
    * @return 
    */ 
    def bucketise(buckets: Seq[Int], candidate: Int): Int = { 

    // x <= y 
    buckets.foldLeft(buckets.head) { (x, y) => 
     val midPoint = (x + y)/2f 

     if (candidate < midPoint) x else y 
    } 
    } 

Ben matematiksel operatörler IntelliJ içinde ( /, +) üzerinde komut tıklayarak çalıştı, ama sadece bir uyarı Sc synthetic function var.

cevap

9

Sadece scala standart kitaplığını kullanmak isterseniz, Numeric[T]'a bakın. Durumunuzda, tamsayı olmayan bir bölüm yapmak istediğinizden, Numeric'un Fractional[T] alt sınıfını kullanmanız gerekir.

Kod, scala standart kitaplık türlerini kullanarak nasıl görüneceğini gösterir. Fractional'un Ordered'dan çıktığını unutmayın. Bu, bu durumda uygundur, ancak matematiksel olarak da jenerik değildir. Örneğin. Sipariş edilmediğinden Complex için Fractional[T] tanımlayamazsınız.

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

Ancak ciddi jenerik sayısal hesaplamalar için ben spire bir göz alarak öneririz. Sayısal tiplerin çok daha ayrıntılı bir hiyerarşisi sağlar. Spire Tipleri ayrıca uzmanlaşmıştır ve bu nedenle çoğu zaman doğrudan ilkellerle çalışmak kadar hızlıdır. İşte

sivri kullanarak olmazdı örnek kullanmak için yapılması gerekenler:

// 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 
    } 
} 

hatta neredeyse aynı böyle örnek (yazabilmesi için, bir Field[T] mevcutsa Spire bile T için tamsayılar otomatik dönüşüm sağlar jenerik olmayan versiyon). Ancak, yukarıdaki örneklerin anlaşılması daha kolay olduğunu düşünüyorum.

// 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 
    } 
} 

Güncelleme: kulesiyle çok güçlü ve jenerik değil, aynı zamanda bir acemi için biraz kafa karıştırıcı olabilir. Özellikle işler işe yaramadığında. İşte temel yaklaşımı ve bazı sorunları açıklayan bir excellent blog post.

+0

Tamam, teşekkürler. Mesele şu ki, Int (http://www.scala-lang.org/api/current/index.html#scala.Int) için scala dokümanlar, uzandığı özellikleri listelemiyorlar. '. Int'nın hangi özelliklerini genişletebileceğimi nasıl öğrenebilirim ki, kendim için “Numeric [T]” yi bulabilirdim? – jbrown

+0

@jbrown Sıralama bir [typeclass] 'dir (http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html). Tipler, devralma kullanılarak çalışmaz. –

+0

Peki, Intel'in hangi tip belgelerin geçerli olduğu belgelerine bakarak nasıl bilebilirdik? – jbrown

İlgili konular