2013-03-06 7 views
13

मैं कंड्यूट और पाइप के बीच अंतर को समझने की कोशिश कर रहा हूं। पाइप, कंड्यूट के विपरीत बचे हुए अवधारणाओं के विपरीत है। बचे हुए के लिए क्या उपयोगी हैं? मैं कुछ उदाहरण देखना चाहता हूं जहां बचे हुए जरूरी हैं।कंड्यूट के बचे हुए लाभ का क्या फायदा है?

और पाइप में बचे हुए अवधारणा नहीं हैं, क्या उनके साथ समान व्यवहार प्राप्त करने का कोई तरीका है?

उत्तर

17

गेब्रियल का मुद्दा है कि बचे हुए पदार्थ हमेशा पार्सिंग का हिस्सा होते हैं दिलचस्प है। मुझे यकीन नहीं है कि मैं सहमत हूं, लेकिन यह सिर्फ पार्सिंग की परिभाषा पर निर्भर हो सकता है।

उपयोग की एक बड़ी श्रेणी है जिसके लिए बचे हुए पदार्थों की आवश्यकता होती है। पार्सिंग निश्चित रूप से एक है: किसी भी समय एक पार्स को किसी प्रकार की लुक की आवश्यकता होती है, तो आपको बचे हुए पदार्थों की आवश्यकता होगी। इसका एक उदाहरण मार्कडाउन पैकेज के getIndented फ़ंक्शन में है, जो कुछ निश्चित लाइनों को एक निश्चित इंडेंटेशन स्तर के साथ अलग करता है, जिससे बाकी लाइनों को बाद में संसाधित किया जा सकता है।

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

असल में, मैं एक स्ट्रीमिंग लाइब्रेरी की मूलभूत मूलभूत विशेषता होने के लिए बचे हुए मानता हूं कि कंड्यूट के लिए नया 1.0 इंटरफ़ेस भी बचाए जाने वाले उपयोगकर्ताओं को विकल्प का खुलासा नहीं करता है। मुझे बहुत कम असली दुनिया के मामलों के बारे में पता है जिन्हें इसे एक तरफ या किसी अन्य तरीके की आवश्यकता नहीं है।

+0

स्पष्टीकरण के लिए धन्यवाद, मैं अब काफी आश्वस्त हूं। इस बीच, मैं इस बारे में सोच रहा था कि कंड्यूट जैसी लाइब्रेरी के शीर्ष पर बचे हुए को कैसे कार्यान्वित किया जाए, जिनके पास उन्हें मूल रूप से नहीं है। विचार यह है कि बचे हुए पदार्थों के साथ एक कंडिशन को एक कंड्यूट लौटने के रूप में दर्शाया जा सकता है '(शायद मैं, आर) '। मेरा प्रयास (कंडिट के लिए) है [यहां] (https://gist.github.com/ppetr/5110909)। –

+0

मुझे लगता है कि आपके पास सही अंतर्ज्ञान है, आपका कार्यान्वयन आंतरिक रूप से काम करने के तरीके के समान ही है। मुझे लगता है कि आपने डबल-बचे हुए मुद्दे की खोज की, यही कारण है कि बचे हुए को कंड्यूट में एकाधिक बचे हुए कन्स्ट्रक्टर के रूप में रखा जाना चाहिए। –

+0

फिर भी [एक अन्य प्रयास] (https://gist.github.com/ppetr/5110909#file-feedback-hs) (जो कि मैं अपने स्कैला लाइब्रेरी में सबसे अधिक उपयोग करूँगा) बचे हुए लोगों को बचे हुए लोगों को एक प्रकार के रूप में देखना है फीडबैक: 'पाइप शून्य I (या तो io) umr' के लिए हम एक आंतरिक विधि का उपयोग करके किसी भी' वाम i' को अपने इनपुट में वापस भेजते हैं जो इस तरह के पाइप को मानक में परिवर्तित करता है। –

15

मैं pipes के लिए उत्तर दूंगा। आपके प्रश्न का संक्षिप्त उत्तर यह है कि आगामी pipes-parse लाइब्रेरी में अधिक सामान्य पार्सिंग ढांचे के हिस्से के रूप में बचे हुए लोगों के लिए समर्थन होगा। मुझे लगता है कि लगभग हर मामले जहां लोग बचे हुए हैं वे वास्तव में एक पार्सर चाहते हैं, यही कारण है कि मैं बचे हुए समस्या को पार्सिंग के सबसेट के रूप में फ्रेम करता हूं। आप पुस्तकालय here के वर्तमान मसौदे को पा सकते हैं।

हालांकि, अगर आप यह समझना चाहते हैं कि pipes-parse इसे कैसे काम करता है, तो बचे हुए बफर को स्टोर करने के लिए केवल StateP का उपयोग करना है। यह केवल निम्न दो कार्यों को परिभाषित करने की आवश्यकता है:

import Control.Proxy 
import Control.Proxy.Trans.State 

draw :: (Monad m, Proxy p) => StateP [a] p() a b' b m a 
draw = do 
    s <- get 
    case s of 
     [] -> request() 
     a:as -> do 
      put as 
      return a 

unDraw :: (Monad m, Proxy p) => a -> StateP [a] p() a b' b m() 
unDraw a = do 
    as <- get 
    put (a:as) 

draw पहले पुशबैक बफर सलाह भी लेता है अगर कोई संग्रहीत तत्व हैं देखने के लिए, ढेर बंद एक तत्व पॉपिंग यदि उपलब्ध है। यदि बफर खाली है, तो यह अपस्ट्रीम से नए तत्व का अनुरोध करता है। बेशक, अगर हम कुछ भी वापस नहीं दबा सकते हैं तो बफर होने का कोई मतलब नहीं है, इसलिए हम बाद में सहेजने के लिए स्टैक पर तत्व को धक्का देने के लिए unDraw को भी परिभाषित करते हैं।

संपादित करें: ओह, मैं बचे हुए उपयोगी होने का एक उपयोगी उदाहरण शामिल करना भूल गया। माइकल की तरह, takeWhile और dropWhile बचे हुए पदार्थों के उपयोगी मामले हैं।

drawWhile :: (Monad m, Proxy p) => (a -> Bool) -> StateP [a] p() a b' b m [a] 
drawWhile pred = go 
    where 
    go = do 
     a <- draw 
     if pred a 
     then do 
      as <- go 
      return (a:as) 
     else do 
      unDraw a 
      return [] 

अब मान लें कि आपकी निर्माता था:: यहाँ drawWhile समारोह (माइकल क्या कॉल्स takeWhile के अनुरूप) है

producer() = do 
    respond 1 
    respond 3 
    respond 4 
    respond 6 

... और आपको लगता है कि एक उपभोक्ता का उपयोग किया जाता को झुका:

consumer() = do 
    evens <- drawWhile odd 
    odds <- drawWhile even 

यदि पहले drawWhile odd ने अंतिम तत्व को वापस धक्का नहीं दिया, तो आप 4 छोड़ देंगे, जो नहीं मिलेगा सही ढंग से दूसरे drawWhile even कथन 'पर पारित किया गया।

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