2012-11-17 13 views
21

दो तर्क का एक Haskell समारोह को फिर से लिखना कर रहा है हास्केल में निम्नलिखित समारोहमैं कैसे बात से मुक्त करने के लिए शैली

agreeLen :: (Eq a) => [a] -> [a] -> Int 
agreeLen x y = length $ takeWhile (\(a,b) -> a == b) (zip x y) 

मैं कैसे लिखने के लिए 'मुहावरेदार' हास्केल है, जो लगता है जानने के लिए कोशिश कर रहा हूँ . और $ कोष्ठक के बजाय, और जहां भी संभव हो पॉइंटफ्री कोड पसंद करना पसंद करते हैं। मैं स्पष्ट रूप से x और y का उल्लेख करने से छुटकारा नहीं पा रहा हूं। कोई विचार?

मुझे लगता है कि मुझे दो तर्कों के किसी भी फ़ंक्शन को पॉइंटफ्रीइंग के साथ एक ही समस्या होगी।

बीटीडब्ल्यू, यह सिर्फ अच्छे कोड लिखने की तलाश में है; कुछ "होमवर्क व्यायाम" इसे पॉइंटफ्री बनाने के लिए जो कुछ भी लेता है उसका उपयोग करें।

धन्यवाद।


(जोड़ा गया टिप्पणी) उत्तर के लिए धन्यवाद। आपने मुझे विश्वास दिलाया है कि यह फ़ंक्शन पॉइंटफ्री से लाभ नहीं उठाता है। और आपने मुझे अभिव्यक्तियों को बदलने के अभ्यास के लिए कुछ बेहतरीन उदाहरण भी दिए हैं। यह अभी भी मेरे लिए मुश्किल है, और वे हास्केल के रूप में आवश्यक होने लगते हैं के रूप में संकेत तुम भी इस्तेमाल कर सकते हैं सी

+2

मुझे hlint (http://community.haskell.org/~ndm/darcs/hlint/hlint.htm) मिला जो मुझे अभिव्यक्ति लिखने के अन्य तरीकों को सीखने में मदद करने में बहुत मूल्यवान है। और $। – mhwombat

उत्तर

41

और जहां भी संभव हो पॉइंटफ्री कोड पसंद करते हैं।

"जहां संभव हो" नहीं, लेकिन "जहां यह पठनीयता में सुधार करता है (या अन्य प्रकट फायदे हैं)"।

बात से मुक्त करने के लिए अपने

agreeLen x y = length $ takeWhile (\(a,b) -> a == b) (zip x y) 

एक पहला कदम ($) सही स्थानांतरित करने के लिए, और की जगह एक तुम एक (.) साथ होगा: अब

agreeLen x y = length . takeWhile (\(a,b) -> a == b) $ zip x y 

, आप इसे ले जा सकते हैं और भी सही:

agreeLen x y = length . takeWhile (uncurry (==)) . zip x $ y 

और वहां आप तुरंत काट सकते हैं एक तर्क बंद,

agreeLen x = length . takeWhile (uncurry (==)) . zip x 

तो फिर तुम कि पुनर्लेखन कर सकते हैं रचना ऑपरेटर का एक उपसर्ग आवेदन के रूप में,

agreeLen x = (.) (length . takeWhile (uncurry (==))) (zip x) 

और आप लिख सकते हैं

च (gx)

रूप

f . g $ x 

आम तौर पर,

f = (.) (length . takeWhile (uncurry (==))) 

और g = zip के साथ यहाँ,

agreeLen x = ((.) (length . takeWhile (uncurry (==)))) . zip $ x 

तर्क x आसानी से निकाल दिया जाता है जहाँ से दे रही है। तो फिर तुम एक वर्ग में (.) का उपसर्ग आवेदन बदल सकता है और

agreeLen = ((length . takeWhile (uncurry (==))) .) . zip 

मिलता लेकिन, कि मूल की तुलना में कम पढ़ी जा सकती है, तो मैं कर सलाह नहीं देते में भाव के परिवर्तन का अभ्यास के लिए छोड़कर बिंदु से मुक्त है कि अंदाज।

+9

वास्तव में उल्लेखनीय बात यह है कि शॉनफिंकेल नाम के एक व्यक्ति ने 1 9 20 में इस तकनीक का आविष्कार किया था। –

11

रहे हैं:

agreeLen :: (Eq a) => [a] -> [a] -> Int 
agreeLen x y = length $ takeWhile id $ zipWith (==) x y 

मुहावरेदार हास्केल जो कुछ भी पढ़ने में आसान है, जरूरी नहीं कि क्या है सबसे अधिक बिंदु मुक्त।

+0

ज़िप का उपयोग करके बहुत अच्छी चीज दिखती है। लेकिन "आसान पढ़ने के लिए" का मेरा संस्करण हास्केल के अधिकांश लेखकों से बहुत अलग है, इसलिए मैं अपने संस्करण को उनके करीब ले जाने की कोशिश कर रहा हूं। – JonathanZ

+3

@ जोनाथन वैसे, यहां तक ​​कि समुदाय की शैली पर अलग-अलग राय भी हैं, लेकिन मैं आपको बता सकता हूं कि जब भी आपके पास एक तर्क के कार्यों की श्रृंखला होती है, तो मेरा अपना सम्मेलन '.' का उपयोग करना है, और यदि आप दो या दो से अधिक तर्कों का उपयोग करते हैं तो आप बस उन्हें स्पष्ट '$' के लिए, आप मुख्य रूप से 'डू' ब्लॉक के अंत में लटकते कोष्ठक को हटाने के लिए इसका उपयोग करते हैं, जैसे 'foo $ do ...', या multiply-nested कोष्ठक को व्यवस्थित करने के लिए। –

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