2012-11-02 33 views
10

के लिए आवेदन किया मैं इस तरह एक विशेषता है:स्काला - सह/विपरीत विचरण के रूप में अंतर्निहित पैरामीटर चयन

def sum[A, B](list: Traversable[A])(implicit adder: CanFold[A, B]): B = 
    list.foldLeft(adder.zero)((acc,e) => adder.sum(acc, e)) 

:

trait CanFold[-T, R] { 
    def sum(acc: R, elem: T): R 
    def zero: R 
} 
एक समारोह है कि इस तरह यह साथ काम करता है के साथ

इरादा इस तरह कुछ करने के लिए है:

implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] { 
    def sum(x: Traversable[A], y: Traversable[A]) = x ++ y 
    def zero = Traversable() 
} 

sum(List(1, 2, 3) :: List(4, 5) :: Nil) 
//=> Traversable[Int] = List(1, 2, 3, 4, 5) 

तो यह प्रकारों के लिए एक प्रकार स्तरीय जिसके लिए पर्यावरण को पहले से ही जानता है कि कैसे करने के लिए गुना और इन्स, स्ट्रिंग्स, जो भी हो, के लिए परिभाषित किया जा सकता है।

मेरे समस्या यह है कि मैं भी अधिक विशेष implicits कि उन्हें प्राथमिकता दी जाएगी, इस तरह करना चाहते है:

implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] { 
    def sum(x: Set[A], y: Set[A]) = x ++ y 
    def zero = Set.empty[A] 
} 

sum(Set(1,2) :: Set(3,4) :: Nil) 
//=> Set[Int] = Set(1, 2, 3, 4) 

हालांकि कि विधि कॉल एक संघर्ष उत्पन्न करता है, के रूप में वहाँ अस्पष्टता:

both method CanFoldSeqs in object ... 
and method CanFoldSets in object ... 
match expected type CanFold[Set[Int], B] 

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

मैं बताकर यहां सोच सकते रही है, लेकिन एक ही आशा कर सकते हैं :-)

उत्तर

14

इस तरह की एक स्थिति में हमेशा की तरह दृष्टिकोण तरीका है कि implicits विरासत द्वारा प्राथमिकता के आधार पर कर रहे हैं का लाभ लेता है:

trait LowPriorityCanFoldInstances { 
    implicit def CanFoldSeqs[A] = new CanFold[Traversable[A], Traversable[A]] { 
    def sum(x: Traversable[A], y: Traversable[A]) = x ++ y 
    def zero = Traversable() 
    } 
} 

object CanFoldInstances extends LowPriorityCanFoldInstances { 
    implicit def CanFoldSets[A] = new CanFold[Set[A], Set[A]] { 
    def sum(x: Set[A], y: Set[A]) = x ++ y 
    def zero = Set.empty[A] 
    } 
} 

import CanFoldInstances._ 

अब लागू होने पर Set इंस्टेंस का उपयोग किया जाएगा, लेकिन Traversable के लिए कोई भी तब भी उपलब्ध नहीं है जब यह नहीं है।