2012-03-15 15 views
5

के साथ एक कुंजी द्वारा समूह मान मैं एक विधि mergeKeys लिखना चाहता हूं जो कुंजी द्वारा Iterable[(K, V)] में मानों को समूहित करता है। उदाहरण के लिए, मैं लिख सकते हैं:किसी भी मोनॉयड

def mergeKeysList[K, V](iter: Iterable[(K, V)]) = { 
    iter.foldLeft(Map[K, List[V]]().withDefaultValue(List.empty[V])) { 
     case (map, (k, v)) => 
      map + (k -> (v :: map(k))) 
    } 
    } 

हालांकि, मैं List के लिए एक विधि लिखने की बजाय किसी भी Monoid उपयोग करने में सक्षम होना चाहते हैं। उदाहरण के लिए, मान पूर्णांक हो सकते हैं और मैं उन्हें सूची में जोड़ने के बजाय उन्हें जोड़ना चाहता हूं। या वे (String, Int) tuples हो सकता है जहां मैं एक सेट में स्ट्रिंग जमा करना चाहता हूं लेकिन पूर्णांक जोड़ना चाहता हूं। मैं इस तरह की एक विधि कैसे लिख सकता हूं? या ऐसा करने के लिए स्कालज़ में मैं कुछ और उपयोग कर सकता हूं?

अपडेट: मैं जितना दूर सोचा था उतना दूर नहीं था। मैं थोड़ी करीब आ गया, लेकिन मुझे अभी भी पता नहीं है कि मूल्य कैसे काम करते हैं, इसे कैसे काम करना है। क्या मुझे अभी तक एक और निहित रूपांतरण लिखने की ज़रूरत है? यानी, प्रत्येक प्रकार के पैरामीटर के लिए एक अंतर्निहित रूपांतरण?

sealed trait SuperTraversable[T, U, F[_]] 
extends scalaz.PimpedType[TraversableOnce[(T, F[U])]] { 
    def mergeKeys(implicit mon: Monoid[F[U]]): Map[T, F[U]] = { 
    value.foldLeft(Map[T, F[U]]().withDefaultValue(mon.zero)) { 
     case (map, (k, v)) => 
     map + (k -> (map(k) |+| v)) 
    } 
    } 
} 

implicit def superTraversable[T, U, F[_]](
    as: TraversableOnce[(T, F[U])] 
): SuperTraversable[T, U, F] = 
    new SuperTraversable[T, U, F] { 
     val value = as 
    } 

उत्तर

6

पहले, जबकि यह अपने प्रश्न के लिए प्रासंगिक नहीं है, तो आप अपने कोड के व्यापकता स्पष्ट प्रकार निर्माता F[_] उल्लेख करते हुए सीमित कर रहे हैं। यह ऐसा करने के बिना ठीक काम करता है:

sealed trait SuperTraversable[K, V] 
extends scalaz.PimpedType[TraversableOnce[(K, V)]] { 
    def mergeKeys(implicit mon: Monoid[V]): Map[K, V] = { 
     value.foldLeft(Map[K, V]().withDefaultValue(mon.zero)) { 
      case (map, (k, v)) => 
       map + (k -> (map(k) |+| v)) 
     } 
    } 
} 

[...] 

अब, अपने वास्तविक प्रश्न के लिए, तो संयोजनों की अजीब प्रकार संभाल करने mergeKeys बदलने के लिए कोई आवश्यकता नहीं है; जो भी आप करना चाहते हैं उसे संभालने के लिए बस Monoid लिखें।

implicit def monoidStringInt = new Monoid[(String, Int)] { 
    val zero = ("", 0) 
    def append(a: (String, Int), b: => (String, Int)) = (a, b) match { 
     case ((a1, a2), (b1, b2)) => (a1 + b1, a2 + b2) 
    } 
} 

println { 
    List(
     "a" -> ("Hello, ", 20), 
     "b" -> ("Goodbye, ", 30), 
     "a" -> ("World", 12) 
    ).mergeKeys 
} 

देता

Map(a -> (Hello, World,32), b -> (Goodbye, ,30)) 
+0

बिल्कुल सही है, धन्यवाद: यदि आप अपने स्ट्रिंग्स + Ints उदाहरण करना चाहता था की शुभकामनाएं दें! – schmmd

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