2009-12-08 10 views
7

स्कैला में, मैं जेनेरिक कक्षाएं लिखने में सक्षम होना चाहता हूं जो ऑपरेटर जैसे>, /, * आदि का उपयोग करते हैं, लेकिन मुझे नहीं लगता कि टी को कैसे बाधित करना है कि यह काम करेगा।स्कैला: जेनेरिक कक्षाओं में संख्यात्मक संचालन करने का सबसे अच्छा तरीका क्या है?

मैंने ऑर्डर्ड [टी] के साथ टी को बाधित करने में देखा, लेकिन ऐसा लगता है कि केवल RichXXX (जैसे RichInt) इसे विस्तारित नहीं करता है, इंट आदि नहीं। मैंने न्यूमेरिक [टी] भी देखा, क्या यह केवल उपलब्ध है स्कैला 2.8? कई टी जो समर्थन नहीं करते> आदि

विचार देखते हैं क्योंकि,

class MaxOfList[T](list: List[T]) { 
    def max = { 
    val seed: Option[T] = None 

    list 
     .map(t => Some(t)) 
     // Get the max  
     .foldLeft(seed)((i,m) => getMax(i,m)) 
    } 

    private def getMax(x: Option[T], y: Option[T]) = { 
    if (x.isDefined && y.isDefined) 
     if (x > y) x else y 
    else if (x.isDefined) 
     x 
    else 
     y 
    } 
} 

इस वर्ग के संकलन नहीं होगा:

यहाँ एक विशिष्ट उदाहरण है?

अभी के लिए मैं एक Mixin विशेषता का उपयोग किया है यह चारों ओर पाने के लिए:

/** Defines a trait that can get the max of two generic values 
*/ 
trait MaxFunction[T] { 
    def getMax(x:T, y:T): T 
} 

/** An implementation of MaxFunction for Int 
*/ 
trait IntMaxFunction extends MaxFunction[Int] { 
    def getMax(x: Int, y: Int) = x.max(y) 
} 

/** An implementation of MaxFunction for Double 
*/ 
trait DoubleMaxFunction extends MaxFunction[Double] { 
    def getMax(x: Double, y: Double) = x.max(y) 
} 

कौन सा अगर हम बदल मूल वर्ग इन्स्टेन्शियशन समय में मिलाया जा सकता है।

पीएस मिच, getMax के अपने पुनः लिखने से प्रेरित है, यहाँ एक और है:

private def getMax(xOption: Option[T], yOption: Option[T]): Option[T] = (xOption,yOption) match { 
    case (Some(x),Some(y)) => if (x > y) xOption else yOption 
    case (Some(x), _) => xOption 
    case _ => yOption 
    } 

उत्तर

9

आप View Bounds उपयोग कर सकते हैं।

संक्षेप में, def foo[T <% U](t: T) एक समारोह है कि किसी भी टी है कि या तो है या परोक्ष एक यू करने के लिए परिवर्तित किया जा सकता है एक इंट एक RichInt में बदला जा सकता है (जो अपने वांछित विधि शामिल हैं) ले जाएगा, यह एक उत्कृष्ट उदाहरण है उपयोग के

class MaxOfList[T <% Ordered[T]](list: List[T]) { 
    def max = { 
    val seed: Option[T] = None 
    list.foldLeft(seed)(getMax(_,_)) 
    } 

    private def getMax(xOption: Option[T], y: T) = (xOption, y) match { 
    case (Some(x), y) if (x > y) => xOption 
    case (_, y) => Some(y) 
    } 
} 

पुनश्च - मैं विकल्प खुद को के बजाय मूल्यों की तुलना करने के लिए अपने getMax (...) विधि दुबारा लिखा है, और isDefined (...)

पी पी एस के बजाय मिलान पैटर्न का इस्तेमाल - स्काला 2.8 होगा एक संख्यात्मक विशेषता है जिसका उपयोग किया जा सकता है। http://article.gmane.org/gmane.comp.lang.scala/16608


परिशिष्ट

बस गिगल्स के लिए, यहाँ सुपर कॉम्पैक्ट संस्करण है कि getMax विधि पूरी तरह समाप्त है:

class MaxOfList[T <% Ordered[T]](list: List[T]) { 
    def max = list.foldLeft(None: Option[T]) { 
     case (Some(x), y) if (x > y) => Some(x) 
     case (_, y) => Some(y) 
    } 
} 

फिर भी एक और परिशिष्ट

इस संस्करण में बड़ी सूचियों के लिए और अधिक कुशल होगा ... के निर्माण से बचा जाता है कुछ (एक्स) प्रत्येक तत्व के लिए:

class MaxOfList[T <% Ordered[T]](list: List[T]) { 
    def max = { 
    if (list.isEmpty) None 
    else Some(list.reduceLeft((a,b) => if (a > b) a else b)) 
    } 
} 

अंतिम एक, मैं वादा!

इस बिंदु पर, तुम सिर्फ वर्ग खाई और एक समारोह का उपयोग कर सकते हैं:

def max[T <% Ordered[T]](i: Iterable[T]) = { 
    if (i.isEmpty) None 
    else Some(i.reduceLeft((a,b) => if (a > b) a else b)) 
    } 
+0

धन्यवाद:

आप कुछ सामान्य कोड के टुकड़े मैं Rosetta Code के लिए लिखा था में रुचि हो सकती। मैं कसम खाता हूँ कि मैंने कोशिश की और इसे संकलित करने के लिए नहीं मिला! –

+0

मैंने आपके द्वारा प्रेरित getMax के एक और संस्करण के साथ मूल प्रश्न में एक अद्यतन जोड़ा। –

+0

मैंने अपने getMax को आपके द्वारा प्रेरित एक और संस्करण के साथ अपडेट किया। कुछ प्रकार की एकता तक पहुंचने से पहले कितने पुनरावृत्तियों? –

2
स्केला 2.8 में Numeric[T] साथ

,

scala> case class MaxOfList[T : Numeric](list: List[T]) { 
    |  def max = if(list.isEmpty) None else Some(list.max) 
    | } 
defined class MaxOfList 

scala> MaxOfList(1::2::3::9::7::Nil).max 

res1: Option[Int] = Some(9) 

scala> MaxOfList(1.5::3.9::9.2::4.5::Nil).max 

res2: Option[Double] = Some(9.2) 

scala> MaxOfList(Nil: List[Byte]).max 

res3: Option[Byte] = None 

scala> 
1

Mitch Blevins द्वारा उत्तर के रूप में, कि क्या दृश्य सीमा है के लिए बने थे। अब, जबकि Numeric कुछ केवल स्कैला 2.8 पर जोड़ा गया है, यह नहीं कि यह किसी भी स्कैला 2.8 सुविधा पर निर्भर नहीं है। कोई भी स्कैला 2.7 पर एक ही काम कर सकता है। फिर मिच

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

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