2015-10-12 8 views
5

I thought मुझे अपने फ़ंक्शन को सभी Ordering[_] प्रकारों में पैरामीटर करने की आवश्यकता है। लेकिन यह काम नहीं करता है।स्कैला में सभी संख्याओं में सामान्य रूप से फ़ंक्शन को परिभाषित करने के लिए कैसे करें?

मैं आवश्यक गणितीय परिचालनों का समर्थन करने वाले सभी प्रकार के लिए निम्न कार्य कैसे कर सकता हूं, और मैं इसे अपने आप से कैसे प्राप्त कर सकता हूं?

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

मैं गणितीय ऑपरेटरों (/, +) IntelliJ में पर आदेश क्लिक करने की कोशिश की, लेकिन सिर्फ एक नोटिस Sc synthetic function मिला है।

उत्तर

9

यदि आप केवल स्कैला मानक पुस्तकालय का उपयोग करना चाहते हैं, तो Numeric[T] पर देखें। आपके मामले में, चूंकि आप एक गैर-पूर्णांक विभाजन करना चाहते हैं, इसलिए आपको Fractional[T]Numeric के उप-वर्ग का उपयोग करना होगा।

यहां स्केल मानक लाइब्रेरी टाइपक्लास का उपयोग करने वाला कोड कैसा दिखाई देगा। ध्यान दें कि FractionalOrdered से फैला है। यह इस मामले में सुविधाजनक है, लेकिन यह गणितीय सामान्य भी नहीं है। जैसे आप 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 पर एक नज़र लेने के सुझाव है। यह संख्यात्मक टाइपक्लास के एक और अधिक विस्तृत पदानुक्रम प्रदान करता है। स्पायर टाइपक्लास भी विशिष्ट हैं और इसलिए अक्सर प्राइमेटिव के साथ काम करने के रूप में तेज़ होते हैं।

यहाँ कैसे उदाहरण का उपयोग करने के शिखर का उपयोग कर लगेगा है:

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

अद्यतन: स्पायर बहुत शक्तिशाली और सामान्य है, लेकिन शुरुआत में कुछ हद तक भ्रमित भी हो सकता है। विशेष रूप से जब चीजें काम नहीं करती हैं। मूल दृष्टिकोण और कुछ मुद्दों को समझाते हुए excellent blog post यहां दिया गया है।

+0

ठीक है धन्यवाद मैं स्पायर की जांच करूंगा। बात यह है कि इंट के लिए स्कैला दस्तावेज़ (http://www.scala-lang.org/api/current/index.html#scala.Int) उन लक्षणों की सूची नहीं सूचीबद्ध करता है, जिन्हें मैं 'ऑर्डरिंग' के बारे में अनुमान लगाता हूं '। मैं कैसे पता लगा सकता हूं कि 'Int' किस विशेषता का विस्तार करता है ताकि मुझे अपने लिए' संख्यात्मक [टी] 'मिल सके? – jbrown

+0

@ जेब्रॉउन ऑर्डरिंग एक [टाइपक्लास] है (http://danielwestheide.com/blog/2013/02/06/the-neophytes-guide-to-scala-part-12-type-classes.html)। टाइपक्लास विरासत का उपयोग करके काम नहीं करते हैं। –

+0

तो दस्तावेजों को देखकर, कैसे टाइप किया जा सकता है, जो टाइपक्लास इंट पर लागू होते हैं? – jbrown

संबंधित मुद्दे

 संबंधित मुद्दे