लकवा क्या हैं?


96

इस क्लासिक पेपर के माध्यम से पढ़ते हुए , मैं समानताओं पर अटक गया हूं। दुर्भाग्य से यह खंड काफी पतला है, और विकिपीडिया पृष्ठ कुछ भी नहीं कहता है।

मेरा हास्केल अनुवाद है:

para :: (a -> [a] -> b -> b) -> b -> [a] -> b
para f base = h
  where
    h []       =   base
    h (x:xs)   =   f x xs (h xs)

लेकिन मैं यह नहीं मानता कि - मेरे पास हस्ताक्षर या वांछित परिणाम के लिए कोई अंतर्ज्ञान नहीं है।

पक्षाघात क्या है, और कार्रवाई में कुछ उपयोगी उदाहरण क्या हैं?


हां, मैंने इन सवालों को देखा है , लेकिन वे सीधे तौर पर समानताएं कवर नहीं करते हैं और केवल उन संसाधनों की ओर इशारा करते हैं जो संदर्भ के रूप में सहायक हो सकते हैं, लेकिन शिक्षण सामग्री नहीं।


1
para f base xs = foldr (uncurry f) base $ zip xs (tail $tails xs), मेखिंक्स।
डैनियल फिशर

इस विकी पृष्ठ के अनुसार , प्रतिरूपता "प्रेरक डेटा प्रकारों पर मॉडल आदिम पुनरावृत्ति"। क्या इसका कोई मतलब / मदद है?
huon

4
जेरेमी गिबन्स का "विखंडन" पेपर, जो मैंने उन सवालों में से एक के लिए एक टिप्पणी में बताया, बहुत उपयोगी शिक्षण सामग्री है। cs.ox.ac.uk/jeremy.gibbons/publications/fission.pdf यह कई पुनरावृत्ति पैटर्न के माध्यम से बहुत स्पष्ट रूप से काम करता है।
स्टीफन टेटली

1
डैनियल के फिर से लिखने को सरल बनाया जा सकता है para f base xs = foldr g base (init $ tails xs) where g (x:xs) = f x xs । यह कॉमन लिस्प कीmaplist याद दिलाता है ।
विल नेस

जवाबों:


110

हाँ, वह है para। कायापलट के साथ तुलना करें, या foldr:

para  :: (a -> [a] -> b -> b) -> b -> [a] -> b
foldr :: (a ->        b -> b) -> b -> [a] -> b

para  c n (x : xs) = c x xs (para c n xs)
foldr c n (x : xs) = c x    (foldr c n xs)
para  c n []       = n
foldr c n []       = n

कुछ लोग प्रतिरूपता को "आदिम पुनरावृत्ति" कहते हैं, इसके विपरीत कैटामोर्फिज्म ( foldr) "पुनरावृति" होता है।

जहां foldrदो मापदंडों को इनपुट डेटा के प्रत्येक पुनरावर्ती सबोबिज के लिए एक पुनरावर्ती संगणित मूल्य दिया जाता है (यहां, यह सूची की पूंछ है), paraपैरामीटर को मूल उपसमूह और मूल्य दोनों से पुनरावर्ती रूप से गणना की जाती है।

एक उदाहरण फ़ंक्शन जिसे अच्छी तरह से व्यक्त किया गया paraहै वह किसी सूची के उचित प्रत्ययों का संग्रह है।

suff :: [x] -> [[x]]
suff = para (\ x xs suffxs -> xs : suffxs) []

ताकि

suff "suffix" = ["uffix", "ffix", "fix", "ix", "x", ""]

संभवतः सरल अभी भी है

safeTail :: [x] -> Maybe [x]
safeTail = para (\ _ xs _ -> Just xs) Nothing

जिसमें "कंस" शाखा अपने पुनरावर्ती संगणित तर्क की उपेक्षा करती है और बस पूंछ वापस देती है। आलसी का मूल्यांकन, पुनरावर्ती अभिकलन कभी नहीं होता है और पूंछ को निरंतर समय में निकाला जाता है।

आप काफी आसानी से परिभाषित foldrकर सकते paraहैं; यह परिभाषित करने के लिए थोड़ा मुश्किल paraहै foldr, लेकिन यह निश्चित रूप से संभव है, और सभी को पता होना चाहिए कि यह कैसे किया जाता है!

foldr c n =       para  (\ x  xs  t ->           c x    t)       n
para  c n = snd . foldr (\ x (xs, t) -> (x : xs, c x xs t)) ([], n)

इसके paraसाथ परिभाषित करने की चाल मूल डेटा की foldrएक कॉपी को फिर से बनाना है, ताकि हम प्रत्येक चरण में पूंछ की प्रतिलिपि तक पहुंच प्राप्त कर सकें, भले ही हमारे पास मूल तक कोई पहुंच न हो। अंत में, sndइनपुट की कॉपी को छोड़ देता है और सिर्फ आउटपुट वैल्यू देता है। यह बहुत कुशल नहीं है, लेकिन यदि आप सरासर अभिव्यक्ति में रुचि रखते हैं, तो आपको paraइससे अधिक नहीं मिलेगा foldr। यदि आप के foldr-encoded संस्करण का उपयोग करते हैं para, तो safeTailसब के बाद रैखिक समय लगेगा, तत्व द्वारा पूंछ तत्व की नकल करना।

तो, यह वह है: paraएक और अधिक सुविधाजनक संस्करण है, foldrजो आपको सूची की पूंछ के साथ-साथ उससे गणना किए गए मूल्य तक तत्काल पहुंच प्रदान करता है।

सामान्य मामले में, एक फ़ाइटर के पुनरावर्ती निर्धारण के रूप में उत्पन्न डेटाटाइप के साथ काम करना

data Fix f = In (f (Fix f))

आपके पास

cata :: Functor f => (f         t  -> t) -> Fix f -> t
para :: Functor f => (f (Fix f, t) -> t) -> Fix f -> t

cata phi (In ff) = phi (fmap (cata phi) ff)
para psi (In ff) = psi (fmap keepCopy   ff) where
  keepCopy x = (x, para psi x)

और फिर से, दो परस्पर निश्चित हैं, उसी paraसे परिभाषित के साथ cata"एक प्रतिलिपि बनाएँ" चाल है

para psi = snd . cata (\ fxt -> (In (fmap fst fxt), psi fxt))

फिर से, paraकोई अधिक अभिव्यंजक नहीं है cata, लेकिन यदि आप इनपुट के उपग्रहों तक आसान पहुंच चाहते हैं, तो अधिक सुविधाजनक है।

संपादित करें: मुझे एक और अच्छा उदाहरण याद आया।

बाइनरी खोज पेड़ों पर विचार करें Fix TreeFजहां से दिया गया है

data TreeF sub = Leaf | Node sub Integer sub

और द्विआधारी खोज पेड़ों के लिए सम्मिलन को परिभाषित करने का प्रयास करें, पहले एक के रूप में cata, फिर एक के रूप में para। आप paraसंस्करण को बहुत आसान पाएंगे , जैसा कि प्रत्येक नोड पर आपको एक सबट्री में सम्मिलित करने की आवश्यकता होगी, लेकिन दूसरे को उसी तरह संरक्षित करें जैसा वह था।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.