7

में फ्लैट है The Little Schemer में जाँच करने के लिए, चाहे सूची सपाट है एक समारोह है सफलता:जांच करें कि सूची हास्केल

is_lat :: [a] -> Bool 
is_lat [] = True 
is_lat ??? 

मैं हमें कैसे पता चलेगा कि पैरामीटर प्रपत्र [[a]] में नहीं है? दूसरे शब्दों में, [1,2,3] एक मान्य इनपुट है, लेकिन [[1,3], [2,4]] और [[[1,2,3]]] नहीं हैं।

मैं इसे रिकर्सिव फ़ंक्शंस में आगे का उपयोग करना चाहता हूं जो यह सुनिश्चित करने के लिए सूचियों को स्वीकार करता है कि मैं केवल फ्लैट सूचियों से निपटता हूं।

संपादित करें: मुझे लगता है कि is_lat :: [a] -> Bool प्रकार हस्ताक्षर के कारण लोग उलझन में हैं। मैं अब सहमत हूं, कि मुझे रनटाइम पर प्रकार की जांच नहीं करनी चाहिए। हालांकि, संकलन समय पर प्रकार की जांच करना संभव है? मैं फ़ंक्शन को केवल फ्लैट सूचियों के लिए कैसे काम कर सकता हूं? या क्या मुझे पूरी तरह से सोचने का तरीका बदलना चाहिए?

+8

सवाल यह है: आप यह क्यों चाहते हैं? आप इस फ़ंक्शन का उपयोग करने की योजना कैसे बनाते हैं? –

+0

यदि आप एक सूची है तो क्या आप शायद प्रत्येक तत्व की जांच कर सकते हैं? – MatijaSh

+5

यदि '[[[1, 2, 3]]]' मान्य इनपुट नहीं है, तो आपके फ़ंक्शन में गलत प्रकार है और आपको उस पर पुनर्विचार करने की आवश्यकता हो सकती है जिसे आप पूरा करने का प्रयास कर रहे हैं। –

उत्तर

19

आप वास्तव में हेस्सेल में योजना के रूप में नेस्टेड सूचियों के बारे में नहीं सोच सकते हैं, क्योंकि वे समान डेटा संरचना नहीं हैं। एक हास्केल सूची समरूप है, जहां एक लिस्प "सूची" वास्तव में गुलाब के पेड़ के करीब है (जैसा कि नीचे सीएएमएमसीएन द्वारा इंगित किया गया है)। एक उदाहरण उदाहरण के रूप में, WYAS48 parsing sectionLispVal को परिभाषित करता है, इस पर एक नज़र डालें।

तुम सच में, वास्तव में, वास्तव में क्रम प्रकार की जाँच करने के लिए है, भले ही यह आम तौर पर एक बुरा विचार और हास्केल में बहुत अपरंपरागत है चाहते हैं, Data.Typeable पर गौर। This response भी उपयोगी हो सकता है।

इस प्रश्न का वास्तविक जवाब यह है कि "आपको लिस्प में की तुलना में हास्केल में अपने तर्कों के बारे में सोचने की ज़रूरत है, जिसके परिणामस्वरूप कभी भी रनटाइम पर यह जांच करने की आवश्यकता नहीं होती है" (और मैं इसे एक सामान्य लिस्पर के रूप में कहता हूं, इसलिए मैं समझता हूं कि किस तरह से निराशाजनक है)।

Addendum: आपके संपादन के जवाब में, हास्केल की प्रकार प्रणाली स्वचालित रूप से यह सुनिश्चित करती है।यदि आपके पास foo :: [Int] -> Int प्रकार का फ़ंक्शन है, उदाहरण के लिए, और आप इसे ["One", "Two", "Three"] या [[1, 2, 3]] पास करते हैं, तो आपको एक संकलन-समय त्रुटि मिल जाएगी जो आपको बताती है कि अभी क्या विस्फोट हुआ और क्यों। यदि आप किसी फ़ंक्शन को विशेषज्ञ बनाना चाहते हैं, तो बस एक और विशिष्ट प्रकार घोषित करें।

उदाहरण के लिए (इस तरह कोड लिखने नहीं है, यह सिर्फ निदर्शी प्रयोजनों के लिए है), कहते हैं कि तुम जैसे

myLookup index map = lookup index map 

एक साधारण कार्य है आप GHCi में इस लोड और :t myLookup चलाते हैं, यह बता दूँगा आप कि फ़ंक्शन का प्रकार myLookup :: Eq a => a -> [(a, b)] -> Maybe b है जिसका अर्थ है कि यह Eq (जो भी आप == चला सकते हैं) प्राप्त करने वाले किसी भी प्रकार की कुंजी ले सकते हैं। अब, कहें कि किसी भी कारण से आप यह सुनिश्चित करना चाहते हैं कि केवल कुंजी के रूप में उपयोग संख्याएं। आप यह सुनिश्चित होता है कि एक अधिक विशिष्ट प्रकार घोषणा

myLookup :: Int -> [(Int, a)] -> Maybe a 
myLookup index map = lookup index map 

अब जोड़कर, भले ही वहाँ समारोह अन्य प्रमुख प्रकार के साथ काम कर से रोक के शरीर में कुछ भी नहीं है, तो आप संकलन समय पर एक प्रकार त्रुटि मिलेगी यदि आप इसे Int इंडेक्स या [(Int, a)] मानचित्र के अलावा कुछ और पास करने का प्रयास करते हैं। नतीजतन, इस

myLookup :: Int -> [(Int, a)] -> Maybe a 
myLookup ix lst = lookup ix lst 

main :: IO() 
main = putStrLn . show $ myLookup 1 [(1, "Foo")] 

संकलन होगा और ठीक चलाते हैं, लेकिन इस

myLookup :: Int -> [(Int, a)] -> Maybe a 
myLookup ix lst = lookup ix lst 

main :: IO() 
main = putStrLn . show $ myLookup "Nope.jpg" [("Foo", 1)] 

न करेंगे। मेरी मशीन पर यह संकलन समय

/home/inaimathi/test.hs:5:35: 
    Couldn't match expected type `Int' with actual type `[Char]' 
    In the first argument of `myLookup', namely `"Nope.jpg"' 
    In the second argument of `($)', namely 
     `myLookup "Nope.jpg" [("Foo", 1)]' 
    In the expression: 
     putStrLn . show $ myLookup "Nope.jpg" [("Foo", 1)] 
Failed, modules loaded: none. 

मुझे उम्मीद है कि आपको आगे भ्रमित नहीं किया जाएगा।

+19

ध्यान दें कि अधिकतर, जब आप वास्तव में, * वास्तव में *, ** वास्तव में ** रनटाइम प्रकार की जांच करना चाहते हैं, तो आप गलत हैं और वास्तव में नहीं चाहते हैं, क्योंकि यह एक खराब दृष्टिकोण है। गतिशील टाइपिंग वाली भाषाओं में भी, स्पष्ट प्रकार के चेक को आमतौर पर खराब रूप माना जाता है। विशेष रूप से, बिल्कुल कोई ऐसी स्थिति नहीं है जहां शुरुआत करने वाले को 'टाइप करने योग्य' के साथ मिलना चाहिए। –

+0

@ सीए.एमसीकैन - सहमत। ओपी से स्निपेट लिस्प्स (और एर्लांग में, मैंने जो देखा है) में एक बहुत ही आम रिकर्सन स्थिति है, जहां आप यह जांचना चाहते हैं कि अगली चीज़ एक परमाणु है या उसके अनुसार एक और अनुक्रम और शाखा है। जब तक आप विषम सूचियों से निपट नहीं रहे हैं तब तक आपको इसे करने की आवश्यकता नहीं है। – Inaimathi

+5

यह उस स्थिति में समझ में आता है क्योंकि विपक्षी कोशिका परंपरागत रूप से लिस्प्स में सभी उद्देश्य डेटा संरचना का एक प्रकार है। हास्केल में, आप उस तरह की संरचना को व्यक्त करने के लिए [गुलाब का पेड़] (http://hackage.haskell.org/packages/archive/containers/0.5.2.1/doc/html/Data-Tree.html) का उपयोग करेंगे। –

13

मानक हास्केल सूचियों के साथ यह असंभव और अनावश्यक दोनों है क्योंकि हास्केल दृढ़ता से टाइप किया गया है; या तो सूची के सभी तत्व स्वयं सूचियां हैं (इस मामले में के लिए टाइप [a] = [[b]] है), या वे नहीं हैं।

उदा। यदि आप एक मिश्रित सूची का निर्माण करने का प्रयास करें, आप संकलक से एक त्रुटि प्राप्त होगी:

Prelude> ["hello", ["world!"]] 

<interactive>:3:12: 
    Couldn't match expected type `Char' with actual type `[Char]' 
    In the expression: "world!" 
    In the expression: ["world!"] 
    In the expression: ["hello", ["world!"]] 
+1

यह मिश्रित सूची के बारे में नहीं है, लेकिन [ए] और [[ए]] –

+10

@ सिंडिकैट: लेकिन वे अलग-अलग प्रकार हैं। पहला एक सूची है जिसका तत्व टाइप 'ए' है। दूसरा एक सूची है जिसका तत्व टाइप '[ए] 'प्रकार है। तो एक फ़ंक्शन जिसके लिए आपके प्रश्न का उत्तर देने का अर्थ होता है वह एक होना चाहिए जो एक सूची लेता है * जहां तत्व विभिन्न प्रकार के होते हैं * ('a' और' [a] 'विशिष्ट होने के लिए)। ऐसी सूचियां विषम हैं, और हास्केल सूचियां नहीं हैं। – gspr

11

समारोह प्रकार [a] -> Bool परोक्ष forall a. [a] -> Bool का मतलब है, दूसरे शब्दों में यह सब संभव तत्व प्रकार की सूचियों के लिए समान रूप से परिभाषित किया है। इसमें [[Int]] या [[[String]]] या घोंसले की कोई भी गहराई शामिल है जो आप सोच सकते हैं। लेकिन यह आपके काम के लिए महत्वपूर्ण नहीं है - तत्व प्रकार क्या है - और नहीं कर सकता है।

जहां तक ​​इस कार्य का संबंध है, इनपुट हमेशा एक सूची है जिसका तत्व कुछ अपारदर्शी, अज्ञात प्रकार हैं। यह कभी भी उसी अपारदर्शी प्रकार वाली नेस्टेड सूचियां प्राप्त नहीं करेगा।

0

ठीक है, मुझे लगता है कि, हास्केल में आप http://ideone.com/sPhRCP तक सीमित हैं:

main = do -- your code goes here 
print $isFlat [Node 1, Node 2, Node 3] 
print $isFlat [Node 1, Node 2, Branch [Node 3, Node 4, Node 5], Node 6] 

data Tree a = Node a | Branch [Tree a] 

isFlat :: [Tree a] -> Bool 
isFlat = all isNode where 
         isNode (Node _) = True 
         isNode _ = False 

गैर सख्ती से टाइप भाषाओं में हर वस्तु रन-टाइम प्रकार की जानकारी है और इस प्रकार बहुरूपी हो सकता है। यह दबावों का एक जटिल नेटवर्क हो सकता है, जैसे स्कैला (यदि आप सी ++ में कम जटिल हैं), या बस "सबकुछ एक वस्तु है, और ऑब्जेक्ट सब कुछ है" जैसे पूरी तरह गतिशील भाषाओं (लिस्प, जेएस, ...) ।
हास्केल कड़ाई से टाइप किया गया है।

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