2012-05-13 10 views
6

मैं निम्नलिखित सामान्य अंतराल वर्ग (कृपया उपयोगकर्ता SOC द्वारा मेरे लिए तैयार की है):स्काला अंतर्निहित संख्यात्मक [टी] साथी वस्तु में

case class Interval[T](from: T, to: T)(implicit num: Numeric[T]) { 
    import num.mkNumericOps // allows us to write from.toDouble and to.toDouble 
    def mid: Double = (from.toDouble + to.toDouble)/2.0 
} 

विशिष्ट उपयोग के मामलों: अंतराल [डबल] या अंतराल [इंट]।

object Interval { 

    def union[T](interval1: Interval[T], interval2: Interval[T])(implicit num: Numeric[T]) = { 
    import num.mkOrderingOps // allows interval1.from min 
    Interval[T](interval1.from min interval2.from, interval1.to max interval2.to) 
    } 

    def intersect[T](interval1: Interval[T], interval2: Interval[T])(implicit num: Numeric[T]) = { 
    import num.mkOrderingOps 
    Interval[T](interval1.from max interval2.from, interval1.to min interval2.to) 
    } 

} 

यह (implicit num: Numeric[T]) और import num.mkOrderingOps दोनों तरीकों के अंदर कॉपी करने के लिए बदसूरत बॉयलरप्लेट है: बाइनरी संघ और चौराहे ऑपरेटरों को जोड़ने के लिए मैं साथी वस्तु में (implicit num: Numeric[T]) के साथ एक समान तरीके का अनुसरण किया। अंतराल ऑब्जेक्ट के स्तर पर, केवल एक बार ऐसा करने का कोई तरीका है?

उत्तर

8

हां वहाँ है।

आयात के साथ पहले। आप इसके बजाय अंतराल के दायरे में Ordering.Implicits._ आयात कर सकते हैं।

object Interval { 
    import Ordering.Implicits._ 

    def union[T](....)(implicit num: Numeric[T]) = { 
    // do not import num.mkOrderingOps 
    ... 
    } 
    ... 
} 
उन implicits साथ

, जब यह एक आदेश आपरेशन मिल जाए, यह अंतर्निहित आदेश के लिए दायरे में दिखेगा (संख्यात्मक एक आदेश है) जहां आपरेशन होता है। और आपके प्रत्येक दिनचर्या में दायरे में एक उचित निहितार्थ होता है। यदि आपको अंकगणितीय परिचालनों की भी आवश्यकता है, तो Numeric.Implicits._

अब भी निहित तर्क के साथ आयात करें। आप def f[T: X](args) बजाय def f[T](args)(implicit someName: X[T])

अंतर लिख सकते है कि आप (आप कर सकते हैं संदर्भ के लिए बाध्य के साथ निहित के लिए एक नाम की जरूरत नहीं है: कि के लिए भाषा का है, जो एक संदर्भ में कहा जाता है बाध्य में एक शॉर्टकट नहीं है implictly [टी] का उपयोग करें, लेकिन फिर यह शायद ही कम है। सौभाग्य से, आप एक नाम अब और आयात Ordering.Implicits._

तो

object Interval { 
    import Ordering.Implicits._ 
    // also import Numeric.Implicits._ if you need +,-,*,/ ... 
    def union[T: Numeric] ... 
    def intersection[T: Numeric] ... 
} 
इसके अलावा
+0

धन्यवाद। अच्छा ब्रेवटी मैंने इस संदर्भ को कभी भी विचार नहीं देखा है। कोई ऐसी चीजें कहां से सीखता है? मैंने स्कैला पर एक पुस्तक पढ़ी, लेकिन मुझे संदर्भ सीमा याद नहीं है। –

+0

उदाहरण के लिए देखें [स्कैला में "संदर्भ बाध्य" क्या है?] (Http://stackoverflow.com/questions/2982276/what-is-a-context-bound-in-scala)। – Jesper

5

NumericInterval ऑब्जेक्ट में टाइप क्लास का उपयोग एक प्रकार पैरामीटर T है जो कहीं भी अपने संलग्न क्षेत्र में बाध्य होना चाहिए। Interval, एक अद्वितीय निरंतर मूल्य होने के नाते, बाध्यकारी प्रदान नहीं कर सकता है। इस विशिष्ट समस्या का

एक समाधान Intervalवर्ग के रूप में आम उदाहरण के तरीकों, जो मामले में वे T के बंधन और के साथ जुड़े Numeric उदाहरण साझा करेंगे में अपने union और intersect संचालन की परिभाषा को स्थानांतरित करने के होगा वर्ग के बाकी,

case class Interval[T : Numeric](from: T, to: T) { 
    import Numeric.Implicits._ 
    import Ordering.Implicits._ 

    def mid: Double = (from.toDouble + to.toDouble)/2.0 
    def union(interval2: Interval[T]) = 
    Interval(this.from min interval2.from, this.to max interval2.to) 
    def intersect(interval2: Interval[T]) = 
    Interval(this.from max interval2.from, this.to min interval2.to) 
} 

अगर, हालांकि, आप इन आपरेशनों की परिभाषा रखना पसंद करते हैं अलग Interval वर्ग, एक दृष्टिकोण से निहित बॉयलरप्लेट की राशि है कि आप throug का पीछा करने की जरूरत को कम करने के लिए एच आपके एपीआई संख्यात्मक [टी] के संदर्भ में अपने उच्च स्तर के वर्ग कक्षाओं को परिभाषित करना है। उदाहरण के लिए,

// Type class supplying union and intersection operations for values 
// of type Interval[T] 
class IntervalOps[T : Numeric] { 
    import Ordering.Implicits._ 

    def union(interval1: Interval[T], interval2: Interval[T]) = 
    Interval[T](interval1.from min interval2.from, interval1.to max interval2.to) 

    def intersect(interval1: Interval[T], interval2: Interval[T]) = 
    Interval[T](interval1.from max interval2.from, interval1.to min interval2.to) 
} 

implicit def mkIntervalOps[T : Numeric] = new IntervalOps[T] 

जो उपयोग कैसा दिखेगा में,

def use[T](i1 : Interval[T], i2 : Interval[T])(implicit ops : IntervalOps[T]) = { 
    import ops._ 
    val i3 = union(i1, i2) 
    val i4 = intersect(i1, i2) 
    (i3, i4) 
} 

एक तीसरा विकल्प इन दो, एक अंतर्निहित परिभाषा का उपयोग अतिरिक्त तरीकों के साथ मूल वर्ग को बेहतर बनाने के, को जोड़ती है

class IntervalOps[T : Numeric](interval1 : Interval[T]) { 
    import Ordering.Implicits._ 

    def union(interval2: Interval[T]) = 
    Interval[T](interval1.from min interval2.from, interval1.to max interval2.to) 

    def intersect(interval2: Interval[T]) = 
    Interval[T](interval1.from max interval2.from, interval1.to min interval2.to) 
} 

implicit def enrichInterval[T : Numeric](interval1 : Interval[T]) = 
    new IntervalOps[T](interval1) 

type Ops[T] = Interval[T] => IntervalOps[T] 

फिर उपयोग में,

def use[T](i1 : Interval[T], i2 : Interval[T])(implicit ops : Ops[T]) = { 
    val i3 = i1 union i2 
    val i4 = i1 intersect i2 
    (i3, i4) 
} 
+0

साथ की जरूरत नहीं है, compainon वस्तु 'Interval' एक अच्छा है निहित रूपांतरण डालने के लिए जगह। फिर, 'उपयोग' विधि के साथ अंतिम उदाहरण में आपको केवल समर्थक की आवश्यकता है 'संख्यात्मक' संदर्भ सीमाओं का उपयोग करें [टी: संख्यात्मक] (i1: अंतराल [टी], i2: अंतराल [टी]) ' – 4e6

+0

धन्यवाद मील। मेरी मिल के लिए बहुत सारी चीजें! –

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