2009-03-16 15 views
20

मैं समझने की कोशिश कर रहा हूं कि पैटर्न मिलान के संबंध में हास्केल सूची की समझ "हुड के तहत" कैसे काम करती है। निम्नलिखित GHCi उत्पादन मेरी बात दिखाता है:पैटर्न मिलान विफल होने पर हास्केल सूची की समझ में कोई त्रुटि क्यों नहीं होती है?

Prelude> let myList = [Just 1, Just 2, Nothing, Just 3] 
Prelude> let xs = [x | Just x <- myList] 
Prelude> xs 
[1,2,3] 
Prelude> 

आप देख सकते हैं, यह "कुछ भी नहीं" छोड़ सकते हैं और केवल "बस" मान चुनने के लिए सक्षम है। मैं समझता हूँ कि सूची एक इकाई के रूप में परिभाषित है (, असली दुनिया हास्केल से स्रोत ch 14।):

instance Monad [] where 
    return x = [x] 
    xs >>= f = concat (map f xs) 
    xs >> f = concat (map (\_ -> f) xs) 
    fail _ = [] 

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

जो मुझे समझ में नहीं आता है, हास्केल कैसे "असफल" फ़ंक्शन को कॉल करने के बारे में जानता है? क्या यह "कंपाइलर जादू" है, या कार्यक्षमता जिसे आप स्वयं हास्केल में लिख सकते हैं? क्या सूची समझ के समान तरीके से काम करने के लिए निम्नलिखित "चयन" फ़ंक्शन लिखना संभव है?

select :: (a -> b) -> [a] -> [b] 
select (Just x -> x) myList  -- how to prevent the lambda from raising an error? 
[1,2,3] 

उत्तर

29

हास्केल के implemenatations आंतरिक रूप से इस तरह सीधे यह नहीं कर सकता है, यह इस तरह से :)

[x | Just x <- myList] 

इसके बारे में सोचने के लिए उपयोगी है ... हो जाता है:

do 
    Just x <- myList 
    return x 

... जो है:

myList >>= \(Just x) -> return x 

अपने प्रश्न का रूप:

जो मुझे समझ में नहीं आता है, हास्केल कैसे "असफल" फ़ंक्शन को कॉल करने के बारे में जानता है?

नोट-इनेशन में, यदि कोई पैटर्न बाध्यकारी विफल रहता है (यानी Just x), तो असफल विधि कहा जाता है।

myList >>= \temp -> case temp of 
    (Just x) -> return x 
    _  -> fail "..." 

तो, हर बार जब आप एक monadic संदर्भ कि विफल हो सकता है में एक पैटर्न मैचों की है, हास्केल fail के लिए एक कॉल सम्मिलित करता है: उपरोक्त उदाहरण के लिए, यह कुछ इस तरह दिखेगा। आईओ के साथ इसे आज़माएं:

main = do 
    (1,x) <- return (0,2) 
    print x -- x would be 2, but the pattern match fails 
+0

धन्यवाद! यह प्रतिक्रिया जो मैं पढ़ रहा हूं उससे मेल खाती है और सूची के अलावा अन्य प्रकार के पैटर्न-मिलान व्यवहार को बताती है। यह मेरे लिए नहीं हुआ था कि संकलक विफल होने पर निर्धारित करने के लिए इस तरह के केस स्टेटमेंट का उपयोग कर सकता है। यह पूरी तरह से समझ में आता है। – Cybis

6

मुझे नहीं लगता कि सूची समझ वाक्य रचना तथ्य यह है कि सूची ([]), या उस बात के लिए Maybe, Monad प्रकार वर्ग का एक उदाहरण होने से कोई लेना देना ज्यादा है है।

सूची comprehensions वास्तव में संकलक जादू या वाक्य रचना चीनी रहे हैं, लेकिन क्योंकि संकलक [] डेटा प्रकार की संरचना को पता है कि संभव है।

यहाँ क्या सूची समझ संकलित किया गया है करने के लिए: (ठीक है, मुझे लगता है, मैं वास्तव में यह GHC के खिलाफ जांच नहीं की)

xs = let f = \xs -> case xs of 
         Just x -> [x] 
         _  -> [] 
    in concatMap f myList 

आप देख सकते हैं, संकलक कॉल करने के लिए नहीं है fail फ़ंक्शन, यह केवल खाली सूची को रेखांकित कर सकता है, क्योंकि यह जानता है कि एक सूची है।


दिलचस्प है, इस तथ्य यह है कि सूची comprehensions वाक्य रचना 'को छोड़ देता है' पैटर्न मैच विफलताओं सामान्य प्रोग्रामिंग के लिए कुछ पुस्तकालयों में प्रयोग किया जाता है। Uniplate library में उदाहरण देखें।


संपादित करें: ओह, और अपने सवाल का जवाब देने, आप अपने select समारोह लैम्ब्डा आप दे दिया साथ फोन नहीं कर सकते हैं। यदि आप इसे Nothing मान के साथ कहते हैं तो यह वास्तव में पैटर्न मिलान विफलता पर असफल हो जाएगा।

आप इसे ऊपर कोड से f समारोह गुजर सकता है, लेकिन select से प्रकार होगा:

select :: (a -> [b]) -> [a] -> [b] 

जो बिल्कुल ठीक है, आप concatMap समारोह का उपयोग कर सकते :-) आंतरिक

इसके अलावा, (अपने तर्क के साथ फ़्लिप) नई select अब सूचियों के लिए monadic बाँध ऑपरेटर के प्रकार है:

(>>=) :: [a] -> (a -> [b]) -> [b] 
xs >>= f = concatMap f xs -- 'or as you said: concat (map f xs) 
+1

अच्छा स्पष्टीकरण, धन्यवाद। जो मैंने पढ़ा है http://en.wikibooks.org/wiki/Haskell/Pattern_ सूची समझ के बारे में मिलान करना गलत होना चाहिए (यह एक विकी है, इसलिए मैं आश्चर्यचकित नहीं हूं)। – Cybis

+0

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

+0

मैं बस इतना कहना चाहता था कि जिस तरह से सूची समझ पैटर्न पैटर्न विफलताओं को छोड़ने के बारे में कुछ खास नहीं है। यह विभिन्न तरीकों से एक टन में किया जा सकता है। वह अनियमित उदाहरण बस आसानी से लिखा जा सकता है 'चर x = ब्रह्मांड x >> = \ case var x -> [x]; _ -> [] 'या पैटर्न मिलान के किसी भी अन्य रूप के साथ। – semicolon

10

rule for desugaring a list comprehension रूप [ e | p <- l ] की अभिव्यक्ति की आवश्यकता है (जहां e एक अभिव्यक्ति, p एक पैटर्न है, और l एक सूची अभिव्यक्ति)

हास्केल के
let ok p = [e] 
    ok _ = [] 
in concatMap ok l 

पिछले संस्करणों की तरह व्यवहार monad comprehensions, जो क्योंकि भाषा से हटा दिया गया था उन्हें do-नोटेशन के साथ पढ़ने और अनावश्यक करना मुश्किल था। (सूची comprehensions निरर्थक भी हैं, लेकिन वे इतनी पढ़ने के लिए मुश्किल नहीं है।) मैं desugaring [ e | p <- l ] लगता एक इकाई के रूप में (या, शून्य के साथ एक इकाई के रूप में, सटीक होना करने के लिए)

की तरह कुछ प्राप्त होते हैं
let ok p = return e 
    ok _ = mzero 
in l >>= ok 

जहां mzeroMonadPlus कक्षा से है। यह बहुत

do { p <- l; return e } 

जो

let ok p = return e 
    ok _ = fail "..." 
in l >>= ok 

को desugars के करीब है जब हम सूची इकाई ले, हम

return e = [e] 
mzero = fail _ = [] 
(>>=) = flip concatMap 

Ie, 3 दृष्टिकोण (सूची comprehensions, इकाई comprehensions है, do अभिव्यक्ति) सूचियों के बराबर हैं।

+0

'ई' टाइप सूची की जरूरी नहीं है। यह नहीं होगा "ठीक है पी = [ई]"? इससे काम बन जाएगा। भले ही, यदि आप जो कहते हैं वह सही है, तो http://en.wikibooks.org/wiki/Haskell/Pattern_matching गलत होना चाहिए। – Cybis

+0

आप सही हैं, मैंने अनुवाद में गलती की है। –

+0

रिपोर्ट कहती है, "सूची समझ इन पहचानों को पूरा करती है" ... नहीं "आपको उन्हें इस तरह अनुवाद करना होगा"। उन्हें बस आपके पास काम करना है जैसा कि आपके पास है :) – porges

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