2012-07-29 8 views
25

मैं एक दिन ऊब गया था और मेरे दिमाग व्यायाम करने के लिए करना चाहता था में एक ही मूल्य बिंदु मुक्त शैली करने के लिए कई कार्यों को लागू करना, तो मैं 99 Haskell Problems करने के लिए फैसला किया है लेकिन अपने आप को उन्हें बिंदु मुक्त शैली में कर रही करने के लिए प्रतिबंधित। एक समस्या यह है कि एक बहुत जब मैं बिंदु मुक्त शैली में बातें कर रहा हूँ पैदा करने लगता है यह है: कैसे आप एक ही मूल्य के लिए कई कार्यों लागू होते हैं जब वे एक स्वतंत्र इकाई के रूप में प्रत्येक परिणाम रखते हुए?हास्केल

foobar x = [id x, reverse x] 

और क्या मैं बिंदु मुक्त अंकन में अब तक लेकर आए हैं: उठाई अंकन का उपयोग

foobar' = `map` [id, reverse] ($ x) 

मुझे लगता है कि x पाने के लिए वहाँ के अंत बंद नहीं कर पा रहे।

उत्तर

25

दूसरों को पहले से ही तैनात किया है तुम ऐसा कैसे Reader इकाई का उपयोग कर सकते हैं, लेकिन यह एक ही रास्ता नहीं है। ऐसा लगता है कि अपने दूसरे समारोह बहुत करीब है। मुझे लगता है कि आप

foobar' x = (`map` [id, reverse]) ($ x) 

पोस्ट करने के बाद से x पहले से ही है एक दायीं स्थिति के पास है, तो आप लगभग संपन्न कर लिया था।सबसे पहले, एक समारोह में खंड ($ x) को बदलने क्योंकि यह थोड़ा आसान है के साथ काम करने के लिए:

-- by the definition of a right operator section 
foobar'2 x = (`map` [id, reverse]) (\y -> ($) y x) 

अगला x

को समारोह दायरे में एक नया वेरिएबल लाने, और लगाने से लैम्ब्डा शरीर से x को दूर
-- lambda abstraction I think... 
foobar'2 x = (`map` [id, reverse]) $ (\z y -> ($) y z) x 

एक समारोह संरचना के रूप में इस आवेदन पुनर्लेखन, और फिर आप ईटा कम कर सकते हैं:

-- by definition of '.' 
foobar'3 x = (`map` [id, reverse]) . (\z y -> ($) y z) $ x 

-- eta reduction 
foobar'4 = (`map` [id, reverse]) . (\z y -> ($) y z) 

अंत में, ध्यान दें कि हम लैम्ब्डा को फ़ंक्शन

-- by definition of `flip` 
foobar'5 = (`map` [id,reverse]) . flip ($) 

के साथ प्रतिस्थापित कर सकते हैं और आपके पास एक बिंदु-मुक्त फ़ॉर्म है।

8

आप पाठक इकाई की Applicative उदाहरण में दिलचस्पी होगी:

instance Applicative (e ->) 

इसका इस्तेमाल करते हुए आप आसानी से एक तर्क वितरित कर सकते हैं:

liftA2 (+) sin cos 3 

यहाँ sin और cos कार्य हैं, दोनों मिलते हैं जिनकी 3. व्यक्तिगत परिणाम मूल्य तो (+) का उपयोग कर मिलाया जाता है। आप आगे (->) की Category उदाहरण के साथ इस गठजोड़ कर सकते हैं, लेकिन (.) और id की cource के विशेष संस्करण पहले से ही Prelude में परिभाषित कर रहे हैं।

पृष्ठभूमि: (e ->) के लिए Applicative उदाहरण वास्तव में स्की पथरी, जहां (<*>)एस Combinator है और pureकश्मीर Combinator है प्रतिनिधित्व करता है।

S f g x = f x (g x) 

यह एक समारोह आवेदन (FG) लेता है और बनाता है दोनों मूल्य एक्स ((fx) (gx) पर निर्भर: एस ठीक दो कार्यों के लिए एक तर्क वितरित करने के लिए प्रयोग किया जाता है)।

9

उपयोग sequence:

> let foobar' = sequence [id, reverse] 
> foobar' "abcde" 
["abcde","edcba"] 
+0

सिर्फ अगर आप बाधाओं के साथ ठीक कर रहे हैं। यह सभी उपयोगों के लिए काम नहीं करेगा। –

+0

@ थॉमसएम। डूबुइसन: क्या बाधाएं? –

+0

@ बेनमिलवुड मैं टाइपक्लास बाधाओं का जिक्र कर रहा हूं। जॉनएल का जवाब 'ए -> [ए]' प्रकार का है। । यह जवाब है, जबकि अच्छे और साफ, के प्रकार 'इकाई ((है -> एक) => एक -> [एक]' –

5

कुछ बुनियादी मुहावरेदार combinators जो बार-बार पॉप अप, और विभिन्न उच्च अवधारणाओं और पुस्तकालयों के साथ reimplemented हैं, लेकिन जो कर रहे हैं अनिवार्य रूप से बहुत ही सरल है। नाम भिन्न हो सकते हैं, और कुछ अन्य के मामले में कार्यान्वयन योग्य हैं:

fork (f,g) x = (f x, g x)    -- == (f &&& g) 
prod (f,g) x = (f $ fst x, g $ snd x) -- == (f *** g) 
pmap f (x,y) = (f x, f y)    -- == (f *** f) 
dup  x = (x,x) 

पाठ्यक्रम uncurry f (x,y) == f x y के आदि इन के साथ एक बहुत, बहुत इस्तेमाल किया जाता है।

&&& और ***first और second के रूप में, Control.Arrow में परिभाषित कर रहे हैं और साथ ही। तब prod (f,id) == first f, prod(id,g) == second g आदि आदि

तो अपने foobar

foobar = (\(a,b)->[a,b]) . fork (id,reverse) 
     = (\(a,b)->[a,b]) . (id &&& reverse) 
     = (\(a,b)->[a,b]) . (id *** reverse) . dup 
     = join $ curry ((\(a,b)->[a,b]) . second reverse) 

हो जाता है कि पिछले एक आप भी Control.Monad और Control.Monad.Instances आयात करने की आवश्यकता के लिए। this question भी देखें।


देर संपादित करें: भी Control.Applicativeertes द्वारा जवाब में संकेत दिया के रूप में उपयोग करते हुए,

 = (:) <*> ((:[]) . reverse) 
+0

,' (:) <*> (शुद्ध रिवर्स) '(' ((-।।।>) आर), [ ] 'आवेदन),' ([आईडी, रिवर्स] <*>) शुद्ध '('[]' आवेदक),' अनुक्रम [आईडी, रिवर्स] '(' ((->) आर) 'मोनाड)। –