9

Scalaz एक विधि इस तरह के Boolean, Option[_], Validation[_, _], Either[_, _] आदि के रूप में विभिन्न ADTS के लिए fold नामित इस विधि मूल रूप से है जो दिए गए एडीटी के लिए सभी संभव मामलों के लिए इसी कार्यों लेता है प्रदान करता है। दूसरे शब्दों में, एक पैटर्न मैच नीचे दिखाया गया है:विकल्प, या तो आदि पर गुना का संबंध क्या है और ट्रैवर्सबल पर गुना है?

x.fold(f, g, ..., z) 

कुछ उदाहरण::

x match { 
    case Case1(a, b, c) => f(a, b, c) 
    case Case2(a, b) => g(a, b) 
    . 
    . 
    case CaseN => z 
} 

के बराबर है

scala> (9 == 8).fold("foo", "bar") 
res0: java.lang.String = bar 

scala> 5.some.fold(2 *, 2) 
res1: Int = 10 

scala> 5.left[String].fold(2 +, "[" +) 
res2: Any = 7 

scala> 5.fail[String].fold(2 +, "[" +) 
res6: Any = 7 

एक ही समय में, एक ही साथ एक ऑपरेशन है Traversable[_] प्रकारों के लिए नाम, जो अपने तत्वों पर कुछ संचालन करने वाले संग्रह पर ट्रैवर करता है, और परिणाम मान जमा करता है। fold/catamorphism - उदाहरण के लिए,

scala> List(2, 90, 11).foldLeft("Contents: ")(_ + _.toString + " ") 
res9: java.lang.String = "Contents: 2 90 11 " 

scala> List(2, 90, 11).fold(0)(_ + _) 
res10: Int = 103 

scala> List(2, 90, 11).fold(1)(_ * _) 
res11: Int = 1980 

क्यों इन दोनों के संचालन में एक ही नाम के साथ की पहचान कर रहे हैं? मैं दोनों के बीच किसी भी समानता/संबंध देखने में विफल रहता हूं। मैं क्या खो रहा हूँ?

उत्तर

7

मुझे लगता है कि आपके पास जो समस्या है, वह यह है कि आप इन चीजों को उनके कार्यान्वयन के आधार पर देखते हैं, न कि उनके प्रकार।

List[A] = Nil 
     | Cons head: A tail: List[A] 

Option[A] = None 
      | Some el: A 

अब, चलो Option के गुना पर विचार करते हैं: प्रकार की इस सरल प्रतिनिधित्व पर विचार करें

fold[B] = (noneCase: => B, someCase: A => B) => B 

तो, Option पर, यह कुछ मूल्य के लिए हर संभव मामले B में कम कर देता है, और लौटाते हैं। अब, चलो List के लिए एक ही बात देखते हैं:

fold[B] = (nilCase: => B, consCase: (A, List[A]) => B) => B 

हालांकि, ध्यान दें कि हम एक पुनरावर्ती कॉल वहाँ है, List[A] पर। हम चाहते हैं कि गुना करने के लिए किसी भी तरह है, लेकिन हम जानते हैं कि एक List[A] पर fold[B] हमेशा B वापस आ जाएगी, तो हम इसे इस तरह पुनर्लेखन कर सकते हैं:

fold[B] = (nilCase: => B, consCase: (A, B) => B) => B 

दूसरे शब्दों में, हम B द्वारा List[A] बदल दिया, क्योंकि तह यह हमेशा वापस आ जाएगी , fold के प्रकार हस्ताक्षर दिए गए। अब, चलो देखते हैं स्काला के (उपयोग के मामले) foldRight के लिए हस्ताक्षर टाइप करते हैं:

foldRight[B](z: B)(f: (A, B) ⇒ B): B 

कहो, कि आप कुछ की याद है?

+0

ओह, तो इसे दोबारा लागू किया जाना है! समझ में आता है, धन्यवाद। – missingfaktor

+2

["कैटोमोर्फिज्म" पर विकिपीडिया पृष्ठ] (http://en.wikipedia.org/wiki/Catamorphism) कहता है, "कार्यात्मक प्रोग्रामिंग में, एक कैटमोर्फिज्म क्रियात्मक प्रोग्रामिंग से मनमाने ढंग से बीजगणित डेटा से ज्ञात सूचियों पर फ़ोल्डरों का एक सामान्यीकरण है प्रकार जिन्हें प्रारंभिक बीजगणित के रूप में वर्णित किया जा सकता है। " इसके बाद यह एरिक मीजर के पेपर "केले, लेंस, लिफाफे और बारबेड वायर के साथ कार्यात्मक प्रोग्रामिंग" को इंगित करता है। मुझे लगता है कि इस विषय को बेहतर समझने के लिए मुझे उस पेपर को पढ़ना चाहिए। विकिपीडिया पेज के अंत में – missingfaktor

+1

@missingfaktor, कैटमोर्फिज्म पर 6 भाग ब्लॉग है जो बहुत ही सुलभ लगता है। मैं अभी इसे पढ़ रहा हूँ। यह एफ # है लेकिन मुझे यकीन है कि आपके लिए कोई समस्या नहीं होगी। – huynhjl

5

यदि आप "फोल्डिंग" के बारे में सोचते हैं, "एक बीज के मूल्य के साथ एक ऑपरेटर के माध्यम से एक कंटेनर में सभी मूल्यों को कंडेनसिंग" के रूप में, और आप एक विकल्प के बारे में सोचते हैं जो एक मूल्य पर हो सकता है, तो यह समझ में आता है।

वास्तव में, foldLeft एक ही हस्ताक्षर है और आप बिल्कुल वैसा ही परिणाम देता है अगर आप कोई भी बनाम एक खाली सूची पर इसका इस्तेमाल, और कुछ बनाम केवल एक ही तत्व के साथ एक सूची पर:

scala> val opt : Option[Int] = Some(10) 
opt: Option[Int] = Some(10) 

scala> val lst : List[Int] = List(10) 
lst: List[Int] = List(10) 

scala> opt.foldLeft(1)((a, b) => a + b) 
res11: Int = 11 

scala> lst.foldLeft(1)((a, b) => a + b) 
res12: Int = 11 

fold है स्केल मानक पुस्तकालय में List और Option दोनों पर भी परिभाषित किया गया है, उसी हस्ताक्षर के साथ (मुझे विश्वास है कि वे दोनों वास्तव में एक विशेषता से इसका उत्तराधिकारी हैं)। और फिर, आप कुछ पर के रूप में एक सिंगलटन सूची में एक ही परिणाम प्राप्त:

scala> opt.fold(1)((a, b) => a * b) 
res25: Int = 10 

scala> lst.fold(1)((a, b) => a * b) 
res26: Int = 10 

मैं Option/Either/आदि पर 100% Scalaz से fold के बारे में निश्चित नहीं हूँ, तुम वहाँ एक अच्छा बिंदु बढ़ा। ऐसा लगता है कि मेरे द्वारा उपयोग किए जाने वाले "फोल्डिंग" से काफी अलग हस्ताक्षर और ऑपरेशन होता है।

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