2014-06-21 4 views
6

लिखने के बाद फ़्लैटन प्रकार वास्तविक जीवन विरासत विधियों के आकार अजीबता और प्रश्न के बिंदु को प्रदर्शित करने के लिए एक खिलौना उदाहरण है।दो defs

आप anotherFunc देख सकते हैं, personList से अधिक मानचित्रण के बाद \/[Throwable,List[\/[Throwable,String]]] जो नहीं करना है लेकिन वापसी प्रकार map ing personList के प्रभाव के प्रकार फैलता है। फिर क्या anotherFunc अंदर नीचे बताया गया है (वास्तव में वहाँ Option("fakeString") या कि में से किसी के बजाय हो रहा और अधिक सार्थक बातें है डेमो प्रयोजन के लिए है।

आवश्यकता mappersonList करने के लिए है और अगर यह right है तो लौट आए List[Person] के प्रत्येक तत्व के साथ कुछ करना से right (पक्ष है कि अलगाव से लौटे गया था)।

कैसे आसान बनाने/anotherFunc की वापसी प्रकार समतल (\/[Throwable,List[String]] वापस जाने के लिए) के लिए। अन्य combinators का उपयोग किया जा सकता है?

case class Person(name :String) 

def personList : \/[Throwable,List[Person]] ={ 
    \/.fromTryCatch{ 
    List(Person("John")) 
    } 
} 

def anotherFunc : \/[Throwable,List[\/[Throwable,String]]]= { 
    personList.map{ pl => 
    pl.map{p => 
     for{ 
     s <- Option("fakeString").\/>(new Throwable("not found")) 
     } yield s 

    } 

    } 
} 

उत्तर

8

नोआ जवाब मूल रूप से सही है, लेकिन आप हमेशा एक map द्वारा एक sequence -इस दो पीछा करने के बजाय traverse का उपयोग करना चाहिए रहे हैं बराबर लेकिन पूर्व है:

इस संस्करण में एक छोटे से मेरी राय में खूबसूरत लग रहा है साफ और एक छोटे से अधिक कुशल:

def anotherFunc: Throwable \/ List[String] = personList.flatMap { pl => 
    pl.traverseU { p => 
    for { 
     // I assume you're doing something more interesting here... 
     s <- Option("fakeString").\/>(new Throwable("not found")) 
    } yield s 
    } 
} 

मैं, एक टिप्पणी के बजाय इस एक जवाब बना रही हूँ हालांकि, कि और अधिक सुरुचिपूर्ण हो सकता है इस तरह की समस्या हल करने के लिए एक और तरीका नहीं है कुछ स्थितियों में।

type OrThrowable[A] = Throwable \/ A  

def personList = ListT[OrThrowable, Person](
    \/.fromTryCatch { List(Person("John")) } 
) 

def anotherFunc: ListT[OrThrowable, String] = personList.flatMap { p => 
    Option("fakeString").\/>(new Throwable("not found")).liftM[ListT] 
} 

अब बस अंत में anotherFunc.run उपयोग करने के लिए: यदि आप disjunctions की सूची के साथ बहुत काम कर रहे हैं, तो आप इसे देखने के लिए कि आपको एक ही स्तर के साथ काम कर रहे हैं बनाने के लिए ListT इकाई ट्रांसफार्मर का उपयोग कर सकते Throwable \/ List[Person] प्राप्त करें और यह आपके वर्तमान कोड के बराबर है (लेकिन बहुत अधिक संक्षेप में)।

+0

मैं 'ट्रैवर्सयू' के बारे में भी सोच नहीं रहा था, अच्छा जवाब! – Noah

+1

धन्यवाद, @ नोहा, और स्कूप के बारे में खेद है- अगर 'ट्रॉवर्स' मैं जो जोड़ रहा था, तो मैं इसे एक टिप्पणी करता। –

5

आप personList और फिर sequenceU भीतरी सूची आप कर सकते हैं flatMap तो मूल रूप से flatten अपनी वापसी के प्रकार:

def anotherFunc: \/[Throwable, List[String]] = { 
    personList.flatMap(
     pl => 
     pl.map(
      p => 
      for { 
       s <- Option("fakeString").\/>(new Throwable("not found")) 
      } yield s 
     ).sequenceU 
    ) 
    } 

Intellij कुछ लाल लाइनों के साथ इस बारे में शिकायत लेकिन यह संकलित करता है तथा मुझे \/-(List(fakeString)) के लिए सही ढंग से प्रिंट करता है।

def anotherFunc2: \/[Throwable, List[String]] = { 
    for { 
     pl <- personList 
     res <- pl.map(p => Option("fakeString").\/>(new Throwable("not found"))).sequenceU 
    } yield res 
    } 
संबंधित मुद्दे