एक आवेदक आपको संदर्भ में किसी संदर्भ में किसी संदर्भ में फ़ंक्शन लागू करने देता है। तो उदाहरण के लिए, आप some((i: Int) => i + 1)
को some(3)
पर लागू कर सकते हैं और some(4)
प्राप्त कर सकते हैं। चलो अब के लिए भूल जाओ। मैं बाद में वापस आऊंगा।
सूची में दो प्रतिनिधित्व हैं, यह या तो Nil
या head :: tail
है। आप foldLeft
का उपयोग कर इस पर गुना करने के लिए इस्तेमाल किया जा सकता है लेकिन वहाँ एक और तरीका से अधिक गुना करने के लिए है यह:
def foldr[A, B](l: List[A], acc0: B, f: (A, B) => B): B = l match {
case Nil => acc0
case x :: xs => f(x, foldr(xs, acc0, f))
}
List(1, 2)
को देखते हुए हम समारोह दाईं ओर से शुरू लागू करने सूची पर गुना - भले ही हम वास्तव में सूची deconstruct बाईं तरफ से!
f(1, f(2, Nil))
इसका उपयोग किसी सूची की लंबाई की गणना करने के लिए किया जा सकता है। List(1, 2)
को देखते हुए:
foldr(List(1, 2), 0, (i: Int, acc: Int) => 1 + acc)
// returns 2
यह भी एक और सूची बनाने के के लिए इस्तेमाल किया जा सकता है:
foldr[Int, List[Int]](List(1, 2), List[Int](), _ :: _)
//List[Int] = List(1, 2)
तो एक खाली सूची और ::
समारोह हम एक और सूची बनाने के लिए सक्षम थे दिया।क्या होगा यदि हमारे तत्व कुछ संदर्भ में हैं? यदि हमारा संदर्भ एक आवेदक है तो हम उस संदर्भ में अभी भी हमारे तत्व और ::
लागू कर सकते हैं। हमारे आवेदक के रूप में List(1, 2)
और Option
के साथ जारी है। हम some(List[Int]()))
से शुरू करते हैं हम फ़ंक्शन को Option
संदर्भ में लागू करना चाहते हैं। यह F.map2
करता है। Option
संदर्भ में दो मान लेते हैं, Option
संदर्भ में दो तर्कों के प्रदान किए गए फ़ंक्शन को रखें और उन्हें एक साथ लागू करें।
तो संदर्भ से बाहर हम संदर्भ में (2, Nil) => 2 :: Nil
है हमने: (Some(2), Some(Nil)) => Some(2 :: Nil)
वापस मूल प्रश्न के लिए जा रहे:
// do a foldr
DList.fromList(l).foldr(F.point(List[B]())) {
// starting with an empty list in its applicative context F.point(List[B]())
(a, fbs) => F.map2(f(a), fbs)(_ :: _)
// Apply the `::` function to the two values in the context
}
मैं क्यों अंतर DList
प्रयोग किया जाता है यकीन नहीं है। मैं जो देखता हूं वह यह है कि यह ट्रैम्पोलिन का उपयोग करता है, इसलिए उम्मीद है कि यह कार्यान्वयन स्टैक को उड़ाने के बिना काम करता है, लेकिन मैंने कोशिश नहीं की है इसलिए मुझे नहीं पता।
इस तरह के सही गुना को लागू करने के बारे में दिलचस्प हिस्सा यह है कि मुझे लगता है कि यह आपको catamorphisms का उपयोग करके बीजगणित डेटा प्रकारों के लिए ट्रैवर्स को लागू करने का दृष्टिकोण प्रदान करता है।
उदाहरण के लिए दिए गए:
trait Tree[+A]
object Leaf extends Tree[Nothing]
case class Node[A](a: A, left: Tree[A], right: Tree[A]) extends Tree[A]
फोल्ड इस तरह परिभाषित किया जा सकता है (जो वास्तव में List
के लिए के रूप में ही दृष्टिकोण पीछा कर रहा है):
def fold[A, B](tree: Tree[A], valueForLeaf: B, functionForNode: (A, B, B) => B): B = {
tree match {
case Leaf => valueForLeaf
case Node(a, left, right) => functionForNode(a,
fold(left, valueForLeaf, functionForNode),
fold(right, valueForLeaf, functionForNode)
)
}
}
और पार का प्रयोग करेंगे कि fold
F.point(Leaf)
साथ और इसे Node.apply
पर लागू करें। हालांकि F.map3
नहीं है, इसलिए यह थोड़ा बोझिल हो सकता है।
भयानक उत्तर जिसके लिए किसी भी बाहरी ज्ञान की आवश्यकता नहीं है – betehess