इसलिए मैंने यह फ़ंक्शन बनाया जो 2 आइटम लेता है और उनकी तुलना करता है और सबसे बड़ी तारीख देता है।

biggerDate :: (Ord a1,Ord a2,Ord a3) => (a3,a2,a1)->(a3,a2,a1)->(a3,a2,a1)
biggerDate (x, x1, x2) (y, y1, y2) = 
  if x2 > y2
  then (x, x1, x2) 
  else if x1 > y1 then (x, x1, x2) else (y, y1, y2)

अब मैं तारीखों की एक सूची बनाने की कोशिश कर रहा हूं और सबसे बड़ी तारीख खोजने के लिए उन सभी की तुलना कर रहा हूं।

मेरे पास दो दूर है

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)

मैं सूची से 2 तत्वों को निकालने और उनकी तुलना करने की कोशिश में फंस गया हूं।

-3
TCripe4 20 सितंबर 2020, 03:50

1 उत्तर

सबसे बढ़िया उत्तर

आइए कार्यात्मक रूप से सोचें और इसके माध्यम से प्रकारों को हमारा मार्गदर्शन करने दें।

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate xs = ???

हम एक सूची लेते हैं और... कुछ करते हैं। खैर, पहला सवाल यह है कि अगर सूची खाली है तो हम क्या करना चाहते हैं? हम इसे कुछ तरीकों से संभाल सकते हैं, लेकिन हमारे उद्देश्यों के लिए हम केवल यह कहेंगे कि यह एक गलती थी और एक त्रुटि का संकेत देते हैं

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate [] = error "Empty list of dates!"
maxDate (x : xs) = ???

ठीक है, अगला सरलतम मामला एकल-तत्व सूची है। उस मामले में, सबसे बड़ी तारीख स्पष्ट रूप से केवल एक ही है। आखिर हमारे पास एक ही विकल्प है।

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate [] = error "Empty list of dates!"
maxDate [x] = x
maxDate (x : xs) = ???

अब हम सामान्य स्थिति के साथ रह गए हैं: हमारी सूची में कई तत्व हैं। मैंने पहले वाले को निकालने के लिए पैटर्न मिलान x : xs का उपयोग किया है। अब हम जो करना चाहते हैं वह यह पता लगाना है कि कौन सा बड़ा है: पहला तत्व या बाकी सूची। हम यह पता लगा सकते हैं कि बाकी सूची में सबसे बड़ा तत्व रिकर्सन के साथ क्या है: maxDate xs। फिर हमें यह पता लगाने की जरूरत है कि वह चीज पहले तत्व x से बड़ी है या छोटी। ऐसा करने के लिए आपने पहले ही एक फ़ंक्शन लिखा है, तो चलिए इसका उपयोग करते हैं।

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate [] = error "Empty list of dates!"
maxDate [x] = x
maxDate (x : xs) = biggerDate x (maxDate xs)

और अब हमारे पास एक कार्यशील कार्यान्वयन है। लेकिन चलो वहाँ नहीं रुकते। आइए इसे बेहतर बनाते हैं।

सबसे पहले, ध्यान दें कि हम इसे (a3, a2, a1) पर किसी भी बाइनरी फ़ंक्शन के लिए कर सकते हैं, न कि केवल biggerDate के लिए। आइए हमारे कार्य को थोड़ा सा सार करें और एक अतिरिक्त तर्क लें

foldDate :: (Ord a1, Ord a2, Ord a3) => ((a3, a2, a1) -> (a3, a2, a1) -> (a3, a2, a1)) -> [(a3, a2, a1)] -> (a3, a2, a1)
foldDate _ [] = error "Empty list!"
foldDate _ [x] = x
foldDate f (x : xs) = f x (foldDate f xs)

मैंने अपने फ़ंक्शन को सामान्य रूप से अधिक उपयोगी बनाने के लिए एक अतिरिक्त तर्क जोड़ा है। अब, maxDate, foldDate का केवल एक विशेष मामला है।

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldDate biggerDate

लेकिन हम आगे बढ़ सकते हैं, जैसा कि यह निकला, foldDate को वास्तव में तारीखों के लिए इसके तर्कों की आवश्यकता नहीं है। यह किसी भी प्रकार पर काम कर सकता है।

fold :: (a -> a -> a) -> [a] -> a
fold _ [] = error "Empty list!"
fold _ [x] = x
fold f (x : xs) = f x (fold f xs)

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = fold biggerDate

अब, हास्केल में Hoogle नामक एक बहुत उपयोगी टूल है। आप इसमें एक टाइप सिग्नेचर प्लग कर सकते हैं, और यह आपको बताएगा कि क्या उस सिग्नेचर से मेल खाने वाली कोई चीज बिल्ट-इन है या किसी प्रसिद्ध हास्केल लाइब्रेरी में है। आइए हमारे सारगर्भित fold फ़ंक्शन के प्रकार को प्लग इन करें: (a -> a -> a) -> [a] -> a. पहले परिणामों में से एक फ़ंक्शन है जिसे foldr1. जबकि स्रोत जो हमने यहां लिखा है उससे थोड़ा अधिक जटिल है, यह पता चलता है कि foldr1 वस्तुतः वही सटीक कार्य है जो हम चाहते हैं। हमें खुद एक fold फंक्शन लिखने की भी जरूरत नहीं पड़ी; यह पहले से ही अंतर्निहित है।

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldr1 biggerDate

वाह् भई वाह! maxDate अब सिर्फ दो शब्द हैं। यह काफी शानदार है। लेकिन हम biggerDate पर भी काम कर सकते हैं। देखें, जैसा कि यह निकला, Ord में 3-टुपल्स चीजों के लिए एक उदाहरण है, जो स्वचालित रूप से पहले तत्व से शुरू होता है, फिर दूसरा, फिर तीसरा। इसलिए, यदि आप अपनी तिथियों को वाईएमडी क्रम में उन्मुख करने के इच्छुक हैं (डीएमवाई के बजाए ऐसा लगता है कि आप अभी कर रहे हैं), तो आपका biggerDate भी आसान हो सकता है।

biggerDate :: (Ord a1,Ord a2,Ord a3) => (a3, a2, a1) -> (a3, a2, a1) -> (a3, a2, a1)
biggerDate x y = if x > y then x else y

यदि आप अभी भी तारीखों को डीएमवाई प्रारूप में प्रिंट करना चाहते हैं, तो आप हमेशा अपने स्वयं के Show उदाहरण के साथ एक कस्टम डेटाटाइप (data Date = Date Int Int Int) को परिभाषित कर सकते हैं, लेकिन अभी के लिए हम वाईएमडी का उपयोग करेंगे क्योंकि यह कुछ चीजें बनाता है सरल।

ठीक है, लेकिन फिर से, आइए सार करते हैं। उस फ़ंक्शन ने टुपल्स के साथ कुछ नहीं किया, इसलिए इसे किसी भी Ord चीजों के लिए काम करना चाहिए, है ना?

bigger :: Ord a => a -> a -> a
bigger x y = if x > y then x else y

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldr1 bigger

ठीक है, उस प्रकार का हस्ताक्षर अब बहुत सारगर्भित दिखता है। आइए हूगल एक बार फिर। देखो और देखो, bigger फ़ंक्शन भी अंतर्निहित है: इसे max. तो हमें bigger की भी जरूरत नहीं पड़ी।

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldr1 max

आइए एक बार फिर से सार करते हैं। maxDate के इस संस्करण में वास्तव में टुपल्स का भी उपयोग नहीं किया गया था, इसलिए इसका प्रकार हस्ताक्षर Ord a => [a] -> a जितना सामान्य हो सकता है। एक और Hoogle के माध्यम से यात्रा हमें बताती है कि वह फ़ंक्शन भी हास्केल में उपलब्ध। तो हमारी अंतिम परिभाषा है

maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = maximum

फ़ंक्शन maxDate शाब्दिक हास्केल में अंतर्निहित है, यदि आप अपने निपटान में अमूर्त तकनीकों का उपयोग करना जानते हैं।

इस सब के बारे में इतने विस्तार से जानने का कारण ठीक यही है। इन पुनरावर्ती परिभाषाओं को स्वयं लिखने के लिए तैयार रहना, विशेष रूप से शुरू करते समय, यह मूल्यवान है, और मैं आपको ऐसा करने की सलाह देता हूं। वास्तव में, बस मानक पुस्तकालय के माध्यम से जा रहे हैं (Data.List विशेष रूप से एक सोने की खान है) और हास्केल सीखते समय आपके द्वारा वहां देखे जाने वाले कार्यों को लागू करना एक अद्भुत अभ्यास है।

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

1
Silvio Mayolo 21 सितंबर 2020, 03:53