2010-06-13 25 views
8

मैंने प्रोग्रामिंग प्रबुद्धता की मेरी यात्रा के हिस्से के रूप में केवल हास्केल की दुनिया में अपने पैर की अंगुली को डुबो दिया है (प्रक्रिया से लेकर ओओपी तक अब तक कार्यात्मक तक)।सीखना हास्केल मानचित्र, फ़ोल्ड, लूप और रिकर्सन

मैं ऑनलाइन Haskell Evaluator ऑनलाइन कोशिश कर रहा हूं।

हालांकि अब मैं एक समस्या पर अटक कर रहा हूँ:

एक साधारण समारोह है कि संख्या की एक सरणी के कुल योग देता है बनाएँ।

एक प्रक्रियात्मक मेरे लिए इस भाषा में काफी आसान है (प्रत्यावर्तन का प्रयोग करके) (ग #):

private int sum(ArrayList x, int i) 
{ 
    if (!(x.Count < i + 1)) { 
     int t = 0; 

     t = x.Item(i); 
     t = sum(x, i + 1) + t; 
     return t; 
    } 
} 

सभी बहुत ठीक लेकिन मेरी हास्केल में असफल प्रयास इस प्रकार था:

let sum x = x+sum in map sum [1..10] 

इस परिणामस्वरूप निम्न त्रुटि (उस उपर्युक्त वेबसाइट से):

Occurs check: cannot construct the infinite type: a = a -> t 

कृपया ध्यान रखें कि मैंने पिछले 30 मिनट के लिए केवल हास्केल का उपयोग किया है!

मैं बस एक उत्तर के लिए नहीं देख रहा हूं लेकिन इसके बारे में और अधिक स्पष्टीकरण।

उत्तर

16

मैं एक जवाब है, लेकिन एक के लिए बस नहीं देख रहा हूँ इसके बारे में अधिक स्पष्टीकरण।

के बाईं ओर = आप एक समारोह x के लिए लागू के रूप में sum का उपयोग करें। कंपाइलर x के प्रकार को नहीं जानता है, इसलिए कंपाइलर x के प्रकार "के लिए खड़े होने के लिए टाइप वैरिएबल a का उपयोग करता है। इस प्रकार इंगित करें कि कंपाइलर sum फ़ंक्शन के परिणाम प्रकार को नहीं जानता है, इसलिए यह परिणाम प्रकार के लिए खड़े होने के लिए t टाइप करता है। अब बाएं हाथ की तरफ संकलक सोचता है कि x का प्रकार a -> t है (a स्वीकार करने वाला कार्य और t लौटा रहा है)।

= दाएं हाथ की तरफ = आप x और sum जोड़ें। हास्केल में सभी प्रकार की संख्याओं को जोड़ा जा सकता है, लेकिन आप केवल दो संख्याएं जोड़ सकते हैं यदि उनके पास समान प्रकार है। तो यहां संकलक मानता है कि sum में x जैसा ही प्रकार है, अर्थात् a टाइप करें।

लेकिन हास्केल में एक पहचानकर्ता के पास एक प्रकार का — हो सकता है जो एक जटिल प्रकार का जटिल हो, लेकिन फिर भी एक प्रकार। यह sum, जिसका प्रकार `संकेत के दोनों किनारों पर ही होना चाहिए शामिल हैं, इसलिए संकलक समीकरण

a = a -> t 

हल करने के लिए a और t है कि इस समीकरण को हल करने के लिए कोई मान नहीं होता कोशिश करता है। यह बस नहीं किया जा सकता है। a कोई ऐसा नहीं है कि a एक फ़ंक्शन के बराबर है जो स्वयं को तर्क के रूप में स्वीकार करता है। इस प्रकार त्रुटि संदेश

cannot construct the infinite type: a = a -> t 

सभी स्पष्टीकरण के साथ भी, यह इतना बड़ा त्रुटि संदेश नहीं है, है ना?

हास्केल में आपका स्वागत है :-)


पी.एस. आप "हेलियम सीखने के लिए" हीलियम की कोशिश कर सकते हैं, जो शुरुआती लोगों के लिए बहुत अच्छे त्रुटि संदेश देता है।

let sum x = x+sum 

क्या योग के प्रकार इस मामले में होगा: इस के पहले भाग में

+0

यह व्यापक व्याख्या थी जिसे मैं ढूंढ रहा था। इसे पढ़ने और आगे पढ़ने के बाद अब मैं इसे थोड़ा बेहतर समझता हूं। – Darknight

12

'योग' मूल्यों की एक सूची लेता है और इसे एक ही मूल्य में कम कर देता है। आप या तो इसे एक स्पष्ट लूप के रूप में लिख सकते हैं (याद रखें कि हास्केल में कोई लूप कीवर्ड नहीं है, लेकिन रिकर्सन का उपयोग करता है)। ध्यान दें कि कैसे परिभाषा सूची के आकार के आधार पर, दो भाग हैं:

mysum []  = 0 
mysum (x:xs) = x + mysum xs 

या अधिक कुशलता से, एक tail-recursive शैली में:

mysum xs = go 0 xs 
    where 
     go n []  = n 
     go n (x:xs) = go (n+x) xs 

हालांकि, हास्केल नियंत्रण संरचनाओं के एक अमीर पुस्तकालय है कि आलसी सूचियों पर काम करते हैं। इस मामले में, एक मूल्य के लिए कमी एक कम मूल्य के साथ किया जा सकता है: एक गुना।

तो mysum लिखा जा सकता है के रूप में:

mysum xs = foldr (+) 0 xs 

उदाहरण के लिए:

Prelude> foldr (+) 0 [1..10] 
55 

आपका गलती एक समय में एक नक्शा है, जो एक सूची बदल देती है, एक ही तत्व का इस्तेमाल किया गया है, बल्कि गुना से अधिक।

मैं सुझाव देता हूं कि आप कार्यात्मक प्रोग्रामिंग की मूल अवधारणाओं के बारे में महसूस करने के लिए शायद "Programming in Haskell" हास्केल के परिचय के साथ शुरू करें। अन्य अच्छी प्रारंभिक सामग्री का वर्णन in this question.

+0

मुझे यकीन है कि नहीं कर रहा हूँ क्या 0 नाटकों का महत्व, क्या आप शून्य के उपयोग पर विस्तार कर सकते हैं? – Darknight

+0

0 गुना में जमा पैरामीटर के लिए प्रारंभिक मान है। यह मूल स्रोत में 'टी' मान है। –

1

आपको एक अच्छा ट्यूटोरियल पढ़ने की जरूरत है, वहां कई बड़ी गलतफहमी हैं।

सबसे पहले मैं आपको सूचियों का मतलब मानता हूं और सरणी नहीं। हास्केल में Arrays मौजूद हैं, लेकिन वे शुरुआती स्तर पर आप कुछ नहीं सामना करेंगे। (उल्लेख नहीं है कि आप [1..10] का उपयोग कर रहे हैं जो संख्या 1 से 10 की सूची है)।

समारोह आप चाहते हैं वास्तव में में बनाया गया है, और योग कहा जाता है, तो हम हमारे कुछ और कॉल करने के लिए होगा, new_sum:

new_sum [] = 0 
new_sum (h:t) = h + (sum t) 
+0

आपका पैटर्न मिलान वाक्यविन्यास गलत है। –

+0

धन्यवाद, कोड को आजमाएं और मेरे प्रकार (मुझे बुरा) जांचें। तय की। –

+0

यह (योग टी) भाग था जिसे मुझे समझने में कठिनाई थी, लेकिन नॉर्मन के जवाब के बाद और इसे पढ़ने के बाद अब समझ में आता है। – Darknight

0

आइए नज़र? यह एक संख्या लेता है और एक ऐसा फ़ंक्शन देता है जो एक संख्या लेता है जो एक संख्या लेता है। यदि आपने इसे लिखा है योग x = + x आपके पास एक ऐसा फ़ंक्शन होगा जो एक संख्या लेता है और फ़ंक्शन + x देता है । और योग = = एक फ़ंक्शन लौटाएगा जो दो पूर्णांक लेता है और उन्हें जोड़ता है।

तो अब दूसरे भाग को देखें। मानचित्र में योग [1.10] नक्शा एक तर्क का एक कार्य करता है और इसे सूची के प्रत्येक तत्व पर लागू करता है।वहां एक संचयक को घुमाने के लिए कोई जगह नहीं है, तो चलिए अन्य फ़ोल्ड फ़ंक्शंस को विशेष फ़ोल्डल, फ़ोल्डर में देखें। ये दोनों एक तर्क और एक प्रारंभिक मूल्य के दो तर्कों का एक कार्य लेते हैं। फोल्ड और फ़ोल्डर के बीच का अंतर उस तरफ है जिस पर वे शुरू होते हैं। एल छोड़ दिया जा रहा है ताकि 1 + 2 + 3 आदि और आर जा रहा है सही 10 + 9 + 8 आदि

देना योग foldl राशि में = (+) 0 [1..10]

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