2013-01-16 11 views
8

के दो कार्यों लागू करने के लिए समारोह मैं ऐसे लैम्ब्डा भाव पुन: उपयोगPointfree (या पुस्तकालय) एकल इनपुट

\x -> (f x, g x) 

जहां मैं दो कार्यों के लिए एक ही इनपुट लागू करते हैं और एक जोड़ी में परिणाम संपुटित के रूप में रहते हैं। मैं एक समारोह इस

combine :: (a -> b) -> (a -> c) -> a -> (b,c) 
combine f g x = (f x, g x) 

कब्जा अब ऊपर लैम्ब्डा अभिव्यक्ति सिर्फ combine f g है लिख सकते हैं। मेरे पास दो प्रश्न हैं।

  1. मुझे यह जानने में दिलचस्पी है कि मानक लाइब्रेरी फ़ंक्शन है जो ऐसा करता है जो मुझे नहीं मिल रहा है।
  2. जिज्ञासा से, मैं इस फ़ंक्शन को पॉइंट-फ्री शैली में फिर से लिखना चाहता हूं, लेकिन मुझे इसके साथ बहुत परेशानी हो रही है।

उत्तर

12
  1. Control.Arrow इस के लिए समारोह (&&&) है। इसमें एक "अधिक सामान्य" प्रकार है, जिसका दुर्भाग्य से अर्थ है कि होगल को यह नहीं मिला है (शायद इसे होगल में एक बग माना जाना चाहिए?)।

  2. आप आमतौर पर pointfree साथ स्वचालित रूप से बात की इस तरह समझ सकते हैं, जो #haskell में lambdabot एक प्लगइन के रूप में है।

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

<shachaf> @pl combine f g x = (f x, g x) 
<lambdabot> combine = liftM2 (,) 

कहाँ liftM2Monad की (r ->) उदाहरण के साथ (a -> b -> c) -> (r -> a) -> (r -> b) -> r -> c टाइप किया है। बेशक, इस बिंदु-मुक्त लिखने के कई अन्य तरीके हैं, जो कि आप किस प्राइमेटिव्स को अनुमति देते हैं उसके आधार पर।

+0

संक्षिप्त जवाब के लिए धन्यवाद, और धन्यवाद। – bshourd

12

मुझे यह जानने में दिलचस्पी है कि मानक लाइब्रेरी फ़ंक्शन है जो ऐसा करता है जो मुझे नहीं मिल रहा है।

टाइप क्लास के कारण याद करना आसान है, लेकिन look at Control.Arrow। सादा Arrow एस को घुमाया या लागू नहीं किया जा सकता है, इसलिए Arrow संयोजक आवश्यकता से पॉइंटफ्री हैं। तो आप उन्हें (->) के विशेषज्ञ हैं, तो आप पाएंगे आप जो चाहते है यह है:

(&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c') 

ऐसे Either के लिए बराबर ऑपरेशन है, जो (->) को विशेष रूप में अन्य, समान काम करता है, कर रहे हैं इस तरह दिखता है:

(|||) :: (a -> c) -> (b -> c) -> Either a b -> c 

जो either जैसा ही है।

जिज्ञासा से, मैं इस फ़ंक्शन को पॉइंट-फ्री शैली में फिर से लिखना चाहता हूं, लेकिन मुझे इसके साथ बहुत परेशानी हो रही है।

आप एक इनपुट डुप्लिकेट बना रहे हैं के बाद से, आपको लगता है कि pointfree करने का कोई रास्ता जरूरत है - सबसे आम तरीका, (->) के लिए Applicative या Monad उदाहरण के माध्यम से है, उदाहरण के लिए \f g ->(,) < $ > च < *> g । यह अनिवार्य रूप से एक अंतर्निहित, इनलाइन Reader मोनैड है, और तर्क को विभाजित किया जा रहा है "पर्यावरण" मान है। इस दृष्टिकोण का उपयोग करना, join f xf x x, pure या return बन const, fmap(.) हो जाता हो जाता है, और (<*>)S combinator\f g x -> f x (g x) हो जाता है।

+2

कंट्रोल.एरो फंक्शंस को याद करने में कठिनाई का कारण यह है कि होगल टाइप प्रकारों को '->' के साथ एकीकृत नहीं करेगा, भले ही प्रकार मिलान हो, इसलिए ['(a -> b) -> (के लिए हुगलिंग -> सी) -> ए -> (बी, सी) '] (http://www.haskell.org/hoogle/?q= (ए + -% 3 ई + बी) + -% 3 ई + (ए + -% 3 ई + सी) + -% 3 ई + ए + -% 3 ई + (बी% 2 सीसी)) '(&&&)' ढूंढने में विफल रहता है। (['Fab -> fac -> fa (b, c) '] के लिए हुगलिंग (http://www.haskell.org/hoogle/?q=f+a+b+-%3E+f+a+c+- % 3E + f + a + (बी% 2 सीसी) काम करता है, जैसा कि (चेतावनी के साथ) ['(~ ~> बी) -> (ए ~> सी) -> (ए ~> (बी, सी)) के लिए हुगलिंग '] (http://www.haskell.org/hoogle/?hoogle=%28a+~%3E+b%29+-%3E+%28a+~%3E+c%29+-%3E+a+~%3E+% 28 बी% 2 सीसी% 2 9)) –

+1

इसके लिए धन्यवाद, यह वही है जो मैं जानना चाहता था। धन्यवाद, होगल के लिए 'ए ~> बी' वाक्यविन्यास को इंगित करने के लिए अंटाल, जिसे मैं नहीं जानता था। – bshourd

6

वास्तव में ऐसा करने के कुछ तरीके हैं। अक्सर आप अधिक कार्य होते हैं या किसी अन्य समारोह है, जो मामले में यह और अधिक सुविधाजनक है अनुप्रयोगी शैली का उपयोग करने के लिए परिणाम में उत्तीर्ण होना

f &&& g 

हालांकि,: सबसे आम तरीका Control.Arrow से (&&&) समारोह का प्रयोग है। तब

uncurry (+) . (f &&& g) 

liftA2 (+) f g 

हो जाता है विख्यात इस एक से अधिक कार्य के साथ प्रयोग किया जा सकता है: मुझे pointfree की ओर इशारा करते के लिए

liftA3 zip3 f g h 
+0

धन्यवाद ।, विवरण "एक से अधिक कार्य के साथ प्रयोग" विशेष रूप से के लिए – bshourd

+1

और ये निश्चित रूप से '' <$> और '' <*> साथ फिर से लिखा जा सकता है:। 'zip3 <$> च <*> जी <*> h' कभी कभी यह liftA का उपयोग कर' से स्पष्ट है * '। –

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