2011-01-26 16 views
10

स्कैला में कई लक्षण हैं जिनका उपयोग आप टाइप क्लास के रूप में कर सकते हैं, उदाहरण के लिए Ordered और Numeric पैकेज scala.math में।संख्यात्मक आदेश से अलग संख्यात्मक व्यवहार क्यों करता है?

मैं, उदाहरण के लिए, एक सामान्य विधि Ordered इस तरह का उपयोग कर लिख सकते हैं:

def f[T <% Ordered[T]](a: T, b: T) = if (a < b) a else b 

मैं Numeric के साथ एक समान बात करना चाहता था, लेकिन यह काम नहीं करता:

def g[T <% Numeric[T]](a: T, b: T) = a * b 

Ordered और Numeric के बीच कोई स्पष्ट विसंगति क्यों है?

मुझे पता है कि यह करने के लिए अन्य तरीके हैं, निम्नलिखित काम करेंगे (एक संदर्भ के लिए बाध्य करता है):

def g[T : Numeric](a: T, b: T) = implicitly[Numeric[T]].times(a, b) 

लेकिन वह सिर्फ * उपयोग करने के लिए दो संख्याओं को गुणा करने में सक्षम होने से अधिक जटिल लग रहा है। Numeric विशेषता में * जैसी विधियां शामिल नहीं हैं, जबकि Ordered में < जैसी विधियां शामिल हैं?

मैं जानता हूँ कि वहाँ भी है Ordering जो आप Numeric के रूप में एक ही तरीके से उपयोग कर सकते हैं, यह भी this answer देखें: अगर आप उन लोगों से अंतर्निहित संख्यात्मक [टी] आयात

def f[A : Ordering](a: A, b: A) = implicitly[Ordering[A]].compare(a, b) 

उत्तर

5

Ordered केवल कुछ साधारण पिंपीड विधियां हैं जो Int या Boolean लौटाती हैं, इसलिए कोई प्रकार की चाल की आवश्यकता नहीं है।

Numeric, दूसरी ओर, ऐसे विधियां हैं जो उपयोग किए गए सटीक उप-वर्ग के आधार पर विभिन्न प्रकारों को वापस करती हैं। इसलिए Ordered मार्कर विशेषता से थोड़ा अधिक है, Numeric एक पूर्ण-विशेषीकृत प्रकार की श्रेणी है।

अपने ऑपरेटरों को वापस पाने के लिए, आप lhs operand पर mkNumericOps (Numeric में परिभाषित) का उपयोग कर सकते हैं।

अद्यतन

मीलों बहुत सही है, mkNumericOps निहित है, इसलिए केवल सांख्यिक की कि उदाहरण का आयात तुम वापस सब जादू दे देंगे ...

12

प्रतीकात्मक ऑपरेटरों उपलब्ध हैं

def g[T : Numeric](a: T, b: T) = { 
    val num = implicitly[Numeric[T]] 
    import num._ 
    a * b 
} 

यदि आप केवल एक ही ऑपरेटर का उपयोग करना चाहते हैं, तो यह स्पष्ट रूप से थोड़ा अनावश्यक है, लेकिन गैर-मामूली मामलों में आयात का ओवरहेड इतना अच्छा नहीं है।

ऑपरेटर स्पष्ट आयात के बिना क्यों उपलब्ध नहीं हैं? डिफ़ॉल्ट रूप से दिखाई देने वाले निहितार्थों के खिलाफ सामान्य विचार यहां लागू होते हैं, शायद अधिक इसलिए क्योंकि इन ऑपरेटरों का व्यापक रूप से उपयोग किया जाता है।

5

आप मीलों 'समाधान कम कर सकते हैं केवल ऐसा करके 1 अतिरिक्त पंक्ति का उपयोग करें:

Numeric[A]#Ops

object Ops { 
    implicit def numeric[A : Numeric](a: A) = implicitly[Numeric[A]].mkNumericOps(a) 
} 

को A : Numeric से एक अंतर्निहित रूपांतरण जोड़ें फिर अपने विधि में गुंजाइश में इस लाने

def g[T : Numeric](a: T, b: T) = { 
    import Ops.numeric 
    a * b 
} 

अधिक जानकारी के लिए Scala ticket 3538 देखें।

+0

अच्छा ... बहुत सुरुचिपूर्ण! –

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