क्या तह के बाद एक पोस्टप्रोसेसिंग कदम के बिना इस शब्द फ़ंक्शन को लागू करना संभव है?


14

रियल वर्ल्ड हास्केल, अध्याय 4, प्रिंट के पेज 98 में पूछा गया है कि wordsक्या सिलवटों का उपयोग करके इसे लागू किया जा सकता है, और यह मेरा सवाल भी है:

क्या यह संभव है? यदि नहीं, तो क्यों? अगर है, तो कैसे?

मैं निम्नलिखित के साथ आया था, जो इस विचार पर आधारित है कि प्रत्येक गैर-स्थान को आउटपुट सूची में अंतिम शब्द (यह otherwiseगार्ड में होता है ) के लिए पूर्व निर्धारित किया जाना चाहिए, और यह कि एक खाली जगह के लिए एक खाली शब्द के ट्रिगर को ट्रिगर करना चाहिए आउटपुट लिस्ट यदि कोई पहले से नहीं है (इसे if- then- में संभाला जाता है else)।

myWords :: String -> [String]
myWords = foldr step [[]]
  where
    step x yss@(y:ys)
      | x == ' ' = if y == "" then yss else "":yss
      | otherwise = (x:y):ys

स्पष्ट रूप से यह समाधान गलत है, क्योंकि स्ट्रिंग के आउटपुट सूची में इनपुट स्ट्रिंग परिणाम में अग्रणी रिक्त स्ट्रिंग में अग्रणी स्थान है।

ऊपर दिए गए लिंक पर, मैंने अन्य पाठकों के लिए प्रस्तावित समाधानों में से कई में देखा है, और उनमें से कई मेरे समाधान के समान काम करते हैं, लेकिन वे आम तौर पर फोल्ड के आउटपुट को "पोस्ट-प्रोसेस" करते हैं, उदाहरण के लिए tailअगर यह है तो एक खाली अग्रणी स्ट्रिंग है।

अन्य दृष्टिकोण टुपल्स (वास्तव में सिर्फ जोड़े) का उपयोग करते हैं, ताकि गुना जोड़ी से निपटता है और अग्रणी / अनुगामी स्थानों को अच्छी तरह से संभाल सकता है।

इन सभी तरीकों में, foldr(या एक अन्य तह, fwiw) वह कार्य नहीं है जो बॉक्स से अंतिम आउटपुट प्रदान करता है; हमेशा कुछ और होता है जिसमें आउटपुट को किसी तरह समायोजित करना होता है।

इसलिए मैं प्रारंभिक प्रश्न पर वापस जाता हूं और पूछता हूं कि क्या यह वास्तव में लागू करना संभव है words(इस तरह से कि यह तह का उपयोग करके अनुगामी / अग्रणी / दोहराया रिक्त स्थान को सही ढंग से संभालता है)। तक परतों का उपयोग करते हुए मेरा मतलब है कि तह समारोह सबसे बाहरी समारोह हो गया है:

myWords :: String -> [String]
myWords input = foldr step seed input

जवाबों:


13

अगर मैं सही ढंग से समझूं, तो आपकी आवश्यकताओं में शामिल हैं

(1) words "a b c" == words " a b c" == ["a", "b", "c"]
(2) words "xa b c" == ["xa", "b", "c"] /= ["x", "a", "b", "c"] == words "x a b c"

इसका तात्पर्य है कि हमारे पास नहीं हो सकता

words = foldr step base

किसी भी stepऔर के लिए base

दरअसल, अगर हमारे पास ऐसा था, तो

words "xa b c"
= def words and foldr
step 'x' (words "a b c")
= (1)
step 'x' (words " a b c")
= def words and foldr
words "x a b c"

और यह विरोधाभास (2)।

आप निश्चित रूप से कुछ के बाद प्रसंस्करण की जरूरत है foldr


1
मुझे यह भाषा और अधिक पसंद है ...
एनरिको मारिया डे एंजेलिस

या यहां तक ​​कि ["xa"] == words "xa" == step 'x' (words "a") == step 'x' (words " a") == words "x a" == ["x", "a"], जिसे गुना की दिशा के लिए एक वैध तर्क होने का लाभ है
साइरो

5

@chi का एक अद्भुत तर्क है कि आप words"a" फोल्ड का उपयोग करके लागू नहीं कर सकते , लेकिन आपने फोल्ड s का उपयोग करके कहा था ।

words = filterNull . words1
    where
    filterNull = foldr (\xs -> if null xs then id else (xs:)) []
    words1 = foldr (\c -> if c == ' ' then ([]:) else consHead c) []
    consHead c []       = [[c]]
    consHead c (xs:xss) = (c:xs):xss

बाहरी और अंतरतम दोनों प्रकार के कार्य सिलवटों के होते हैं। ;-)


मुझे लगता है कि आप जानते हैं कि मेरा क्या मतलब है, लेकिन पिकी होने के लिए +1: पी
एनरिको मारिया डे एंजेलिस

1

हाँ। अंततः यह थोड़ा मुश्किल है कि आप अभी भी एक एकल का उपयोग करके इस काम को ठीक से कर सकते हैं foldrऔर यदि आप सीपीएस ( कंटीन्यूएशन पासिंग स्टाइल ) में रहते हैं तो कुछ नहीं । मैंने पहले एक खास तरह का chunksOfफंक्शन दिखाया था ।

इस प्रकार के हमारे संचयकर्ता को तह करते हैं, इसलिए गुना का परिणाम एक कार्य है और हमें इसे एक पहचान प्रकार के इनपुट पर लागू करना होगा ताकि हमारे पास अंतिम परिणाम हो। तो यह अंतिम प्रसंस्करण चरण के रूप में गिना जा सकता है या नहीं, क्योंकि हम यहां एक गुना का उपयोग कर रहे हैं और इसके प्रकार में फ़ंक्शन शामिल है। बहस के लिए खुला :)

ws :: String -> [String]
ws str = foldr go sf str $ ""
         where
         sf :: String -> [String]
         sf s = if s == " " then [""] else [s]
         go :: Char -> (String -> [String]) -> (String -> [String])
         go c f = \pc -> let (s:ss) = f [c]
                         in case pc of
                            ""        -> dropWhile (== "") (s:ss)
                            otherwise -> case (pc == " ", s == "") of
                                         (True, False)  -> "":s:ss
                                         (True, True)   -> s:ss
                                         otherwise      -> (pc++s):ss

λ> ws "   a  b    c   "
["a","b","c"]

sf : प्रारंभिक फ़ंक्शन मान के साथ शुरू करने के लिए।

go : इटरेटर फ़ंक्शन

हम वास्तव में सीपीएस की शक्ति का पूरी तरह से उपयोग नहीं कर रहे हैं क्योंकि हमारे पास पिछले चरित्र pcऔर cहर मोड़ पर सही चरित्र है । यह बहुत ही उपयोगी था chunksOfसमारोह जबकि एक बेडौल ऊपर उल्लेख [Int]में [[Int]]हर बार तत्वों की एक आरोही अनुक्रम टूट गया था।

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