2014-10-28 3 views
32

मैं के बारे में पार, traverseU और traverseM उपयोग मामले के बारे में उलझन में हूँ, मैं scalaz वेबसाइट में, सरल कोड उदाहरण यह खोज:पार समझने के लिए कैसे, traverseU और traverseM

def sum(x: Int) = x + 1 

List(1,2,3).traverseU(sum) 

यह लग रहा है यह है की तरह (मानचित्र और कुल) के समान:

List(1,2,3).map(sum).reduceLeft(_ + _) 

मुझे लगता है कि यह है कि traverseU के लिए की तुलना में अधिक है, मैं सिर्फ आश्चर्य है कि क्या उन 3 विधि के बीच का अंतर है, यह बेहतर होगा मैं दिखाने के लिए कुछ नमूना कोड होगा अंतर

अग्रिम

उत्तर

60

sequence में बहुत धन्यवाद लिए किया जाता है एक साथ इकट्ठा अनुप्रयोगी प्रभाव। अधिक ठोस रूप से, यह आपको F[G[A]] से G[F[A]] पर "फ्लिप" करने देता है, बशर्ते GApplicative और FTraversable है। इसलिए हम इसे उपयोग कर सकते हैं Applicative प्रभाव (ध्यान दें कि सभी Monad रों Applicative कर रहे हैं) का एक समूह "एक साथ खींच" करने के लिए:

List(Future.successful(1), Future.successful(2)).sequence : Future[List[Int]] 
// = Future.successful(List(1, 2)) 
List(4.set("abc"), 5.set("def")).sequence : Writer[String, List[Int]] 
// = List(4, 5).set("abcdef") 

traverse, तो mapsequence के बराबर है जब आप एक समारोह है, तो आप इसे उपयोग कर सकते हैं कि एक Applicative वापस आती है और तुम सिर्फ बजाय उन्हें की एक सूची की तुलना में अपने Applicative का एक उदाहरण प्राप्त करना चाहते हैं:

def fetchPost(postId: Int): Future[String] 
//Fetch each post, but we only want an overall `Future`, not a `List[Future]` 
List(1, 2).traverse[Future, String](fetchPost): Future[List[String]] 

traverseUtraverse रूप में एक ही आपरेशन है , बस अलग-अलग प्रकार के व्यक्त किए गए हैं ताकि संकलक उन्हें अधिक आसानी से अनुमान लगा सकें।

def logConversion(s: String): Writer[Vector[String], Int] = 
    s.toInt.set(Vector(s"Converted $s")) 
List("4", "5").traverseU(logConversion): Writer[Vector[String], List[Int]] 
// = List("4", "5").map(logConversion).sequence 
// = List(4.set("Converted 4"), 5.set("Converted 5")).sequence 
// = List(4, 5).set(Vector("Converted 4", "Converted 5")) 

traverseM(f)traverse(f).map(_.join), जहां joinflatten के लिए scalaz नाम है के बराबर है। यह "flatMap उठाने" का एक प्रकार के रूप में उपयोगी होता है: जहाँ तक के रूप में क्योंकि

def multiples(i: Int): Future[List[Int]] = 
    Future.successful(List(i, i * 2, i * 3)) 
List(1, 10).map(multiples): List[Future[List[Int]]] //hard to work with 
List(1, 10).traverseM(multiples): Future[List[Int]] 
// = List(1, 10).traverse(multiples).map(_.flatten) 
// = List(1, 10).map(multiples).sequence.map(_.flatten) 
// = List(Future.successful(List(1, 2, 3)), Future.successful(List(10, 20, 30))) 
//  .sequence.map(_.flatten) 
// = Future.successful(List(List(1, 2, 3), List(10, 20, 30))).map(_.flatten) 
// = Future.successful(List(1, 2, 3, 10, 20, 30)) 
+0

धन्यवाद, मैं वोट दें, तो मैं बस आश्चर्य आप का उल्लेख किया है कि पार और traverseU के बीच का अंतर प्रकार निष्कर्ष है, इस फर्क सिर्फ इतना है, मैं चिंतित हूं, मैं ट्रैवर्स –

+1

की बजाय ट्रैवर्सयू का उपयोग करूंगा हां, यह एकमात्र अंतर है। (तकनीकी रूप से यह अनुमान लगाने के लिए एक अतिरिक्त पैरामीटर का उपयोग करता है, लेकिन मैं उम्मीद करता हूं कि JVM इसे ऑप्टिमाइज़ करने के लिए)। ऐसे मामले में जहां 'traverseU' * * प्रकार पैरामीटर का अनुमान नहीं लगाता है और आपको उन्हें हाथ से निर्दिष्ट करने की आवश्यकता होती है (या यदि आप जेनेरिक कोड लिख रहे हैं, जहां आप जिस प्रकार का ट्रैवर्सिंग कर रहे हैं वह स्वयं एक प्रकार पैरामीटर है), तो यह आसान है 'ट्रैवर्स' (जिसमें अनुमान सहायक नहीं है) के साथ करें, लेकिन मुझे लगता है कि यह एकमात्र ऐसा मामला है जहां आप कभी भी 'ट्रैवर्सयू' – lmm

+0

बीटीडब्ल्यू के बजाय' ट्रैवर्स 'का उपयोग करना चाहते हैं, मुझे लगता है कि कोड भविष्य होना चाहिए। अब Future.successful के बजाय, क्योंकि पिछला एक स्केलज़ से है, इसलिए इसका अंतर्निहित मूल्य होगा, लेकिन बाद में मानक लाइब्रेरी में से एक में निहित संकल्प –

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