2012-10-30 17 views
5

में 3 तर्कों को घुमाएं मुझे हास्केल में तीन तर्कों को हटाने के लिए एक फ़ंक्शन को घुमाने में समस्या हो रही है।Haskell

अस्वीकरण: कोर्सवर्क नहीं, मुझे इस प्रश्न से आज किसी के साथ संघर्ष करने के लिए कहा गया था और यह मुझे परेशान कर रहा है।

कस्टम प्रकार/कार्य हम दिए गए थे (केवल प्रकार याद कर सकते हैं)

type MyThing 
    = (Char, String) 
type MyThings 
    = [MyThing] 

funcA :: MyThings -> String -> String 
funcB :: MyThings -> String -> Int -> String 

हम साथ शुरू किया था:

funcB as str n = iterate (funcA as) str !! n 

और यह नीचे कम इस प्रकार है:

funcB as str n = iterate (funcA as) str !! n 
funcB as str = (!!) . (iterate (funcA as)) str 
funcB as = (!!) . (iterate (funcA as)) 
funcB as = (!!) . (iterate . funcA) as 

फिर, अटक गया। हम सिर्फ अंतिम तर्क का उपयोग करने से बचने के बारे में नहीं समझ सकते हैं। मुझे पता है कि मैंने पहले एक समान स्थिति देखी है और एक समाधान था।

उम्मीद कुछ हास्केल प्रतिभा का कहना है सकते हैं कारण है कि मैं एक मूर्ख जा रहा हूँ ...

+0

तुम सिर्फ इस्तेमाल कर सकते हैं [ 'pointfree'] (http://www.haskell.org/: तो ऊपर अभिव्यक्ति काफी आसानी से

(!!) ((f . g) x y) n = f (g x) y !! n 

यह देखते हुए कि (.) साहचर्य है के रूप में वापस पढ़ा जा सकता है हैस्सेलविकि/प्वाइंटफ्री # टूल_एक्सटी) स्वचालित रूप से ऐसा करने के लिए। – kennytm

+1

ग्रेट चिल्लाओ, उसमें देखेंगे! –

उत्तर

10

सभी तुम यहाँ की जरूरत ऑपरेटर वर्गों के निम्नलिखित तीन "कानून" है:

(a `op` b) = (a `op`) b = (`op` b) a = op a b 
      (1)   (2)   (3) 

ताकि संकार्य ऑपरेटर के पास नि: शुल्क स्लॉट में चला जाता है।

(.) के लिए इसका मतलब है कि: (a . b) = (a .) b = (. b) a = (.) a bस्पष्ट मूल की तुलना में और वास्तव में, - तो, ​​

f (g x) y !! n  
= (!!) (f (g x) y) n    by (3) 
= ((!!) . f (g x)) y n 
= ((!!) . (f . g) x) y n 
= ((!!) .) ((f . g) x) y n  by (1) 
= (((!!) .) . (f . g)) x y n 
= (((!!) .) . f . g) x y n 

आप केवल के रूप में ज्यादा pointfree परिवर्तन के रूप में आप आरामदायक महसूस करें कि परिणामी अभिव्यक्ति अभी भी पठनीय आपके लिए है करना चाहिए,। "पॉइंटफ्री" टूल कभी-कभी अपठनीय परिणामों का उत्पादन कर सकता है।

मध्य में रुकना बिल्कुल ठीक है। यदि मैन्युअल रूप से इसे पूरा करने के लिए आपके लिए बहुत मुश्किल है, तो शायद आपके लिए इसे पढ़ने में भी मुश्किल होगी।

((a .) . b) x y = (a .) (b x) y = (a . b x) y = a (b x y)सामान्य पैटर्न है कि आप तुरंत तुरंत पहचानना सीखेंगे।

(a . b . c) = ((a . b) . c) = (a . (b . c)) 
+1

ग्रेट उत्तर, धन्यवाद! –

10
funcB = ((!!) .) . iterate . funcA 

मुझे लगता है कि आप सभी कड़ी मेहनत किया है, और सिर्फ एक छोटे से कदम बचा था।

आप वास्तव में इसे pointfree के साथ स्वचालित रूप से कर सकते हैं। HaskellWiki page

देखें कि यह github readme में कहते हैं, एक बार आप इसे स्थापित किया है, तो आप लाइन

:def pf \str -> return $ ":! pointfree \"" ++ str ++ "\"" 

के साथ अपने ghci.conf या .ghci फ़ाइल को संपादित कर सकते हैं और फिर GHCi में आप टाइप जब

:pf funcB as = (!!) . (iterate . funcA) as 

या यहाँ तक कि

:pf funcB as str n = iterate (funcA as) str !! n 
funcB as = (!!) . (iterate . funcA) as 
funcB as = (.) (!!) ((iterate . funcA) as) 

एक बार जब आप यहाँ मिल गया है, तो आप यह मानते हुए कि यह है के आधे का मौका है:आप

funcB = ((!!) .) . iterate . funcA 
+3

यह ईटा कमी नहीं है। ईटा कमी ~ \ x -> ई x' से 'e' तक बढ़ रही है। आपके द्वारा दिया गया परिवर्तन ('x x -> f (g x)' से 'f। G' 'से आगे बढ़ रहा है) कुछ और है - शायद' (।) 'का डेल्टा विस्तार? –

+0

यदि आप थोड़ा और सावधानीपूर्वक पढ़ते हैं तो आप देखेंगे कि मैंने आपके द्वारा किए गए परिवर्तन को नहीं बनाया है! – AndrewC

+0

हाँ, मुझे बाद में एहसास हुआ कि डेल्टा विस्तार केवल आपके द्वारा किए गए परिवर्तन का एक हिस्सा था, लेकिन यह पहले से ही पांच मिनट के नो-टेकबैक चिह्न को पार कर चुका था! –

4

मुझे के लिए महत्वपूर्ण अवलोकन है कि इन्फ़िक्स ऑपरेटरों उपसर्ग लिखा जा सकता है मिल दूसरा तर्क के रूप में एक रचना, (.) (!!) पहले तर्क के रूप में और iterate . funcA साथ:

funcB as = ( ((.) (!!)) . (iterate . funcA) ) as 

अब यह स्पष्ट है कि इसे कैसे सरल बनाना है; इसके बाद, इसे लिखने के बारे में बहुत सारे सौंदर्य विकल्प हैं। उदाहरण के लिए, हम देख सकते हैं कि (.) सहयोगी है, और इसलिए हम कुछ कोष्ठक छोड़ सकते हैं; इसी प्रकार, अगर आप सोचते हैं कि यह अधिक पठनीय है तो हम अजीब ((.) (!!)) मर्ज करने के लिए ऑपरेटर अनुभागों का उपयोग कर सकते हैं।

funcB = ( ((.) (!!)) . (iterate . funcA) ) 
funcB = (.) (!!) . iterate . funcA -- uncontroversial parenthesis removal 
funcB = ((!!) .) . iterate . funcA -- possibly controversial section rewrite 

वैसे, मुझे नहीं लगता कि आपके व्युत्पन्न की शुरुआत सही है। आप सही निष्कर्ष पर पहुंचे, लेकिन गलत मध्य चरणों के माध्यम से।सही किया, यह इस तरह दिखना चाहिए:

funcB as str n = iterate (funcA as) str !! n 
funcB as str n = (!!) (iterate (funcA as) str) n 
funcB as str = (!!) (iterate (funcA as) str) 
funcB as = (!!) . iterate (funcA as) 
संबंधित मुद्दे