2011-08-28 40 views
24

uncurry समारोह केवल कार्यों दो तर्क लेने के लिए काम करता है:क्या हैस्केल में विविध कार्य/टुपल्स हैं?

uncurry :: (a -> b -> c) -> (a, b) -> c 

मैं युक्तियों के स्वेच्छाचारी संख्या के साथ काम करता है uncurry चाहते हैं, मैं सिर्फ अलग कार्यों लिख सकते हैं:

uncurry2 f (a, b)   = f a b 
uncurry3 f (a, b, c)  = f a b c 
uncurry4 f (a, b, c, d) = f a b c d 
uncurry5 f (a, b, c, d, e) = f a b c d e 

लेकिन यह हो जाता है जल्दी थकाऊ क्या इसे सामान्यीकृत करने का कोई तरीका है, इसलिए मुझे केवल एक समारोह लिखना है?

+0

इस तरह से नहीं, लेकिन किसी भी मामले में, आप ऐसा क्यों करना चाहते हैं? मेरे अनुभव में बहुत कम मामले हैं जहां आपको uncurry2 –

+7

@ पॉल से अधिक की आवश्यकता है: कोई विशिष्ट कारण नहीं है, लेकिन जैसे ही मैं किसी भी तरह का दोहराव पैटर्न देखता हूं, मैं खुद से पूछता हूं कि मैं इसे कैसे सामान्य और अमूर्त कर सकता हूं। – fredoverflow

उत्तर

23

tuple पैकेज से uncurryN की कोशिश करो। ओवरलोडिंग के सभी रूपों की तरह, इसे टाइप क्लासेस का उपयोग करके कार्यान्वित किया जाता है। इस मामले में 15-टुपल्स तक के उदाहरणों को मैन्युअल रूप से वर्तनी करके, जो पर्याप्त से अधिक होना चाहिए।

टाइप क्लास का उपयोग करके वैराडिक फ़ंक्शन भी संभव हैं। इसका एक उदाहरण Text.Printf है। इस मामले में, यह फ़ंक्शन प्रकार पर संरचनात्मक प्रेरण द्वारा किया जाता है। सरलीकृत, यह इस तरह काम करता है:

class Foo t 

instance Foo (IO a) 
instance Foo b => Foo (a -> b) 

foo :: Foo 

यह देखने के लिए कि foo प्रकार IO a, a -> IO b, a -> b -> IO c और इतने पर करने के लिए instantiated किया जा सकता है मुश्किल नहीं होना चाहिए। QuickCheck इस तकनीक का भी उपयोग करता है।

स्ट्रक्चरल प्रेरण, tuples पर काम करेंगे नहीं है, हालांकि, के रूप में एक n -tuple पूरी तरह से एक n + 1 -tuple से संबंधित नहीं है, तो यह है कि क्यों उदाहरणों मैन्युअल रूप से बताया जा करना है।

+5

अमानवीय, 'Data.Tuple.Curry' के स्रोत का उल्लेख है कि विभिन्न उदाहरण वास्तव में एक अलग कार्यक्रम द्वारा उत्पन्न किए गए थे, और फिर संभावित रूप से चिपकाया गया था जैसे कि उन्हें हाथ से टाइप किया गया था। –

2

कोई सरल तरीके uncurry की एक एकल परिभाषा यह है कि बहस के विभिन्न संख्या के लिए काम करेगा लिखने के लिए नहीं है।

हालांकि, यह Template Haskell उपयोग करने के लिए कई अलग अलग वेरिएंट कि आप अन्यथा हाथ से लिखने के लिए होता है उत्पन्न करने के लिए संभव है।

+0

आप दानियत फ्रिडलेंडर और मिया इंडिका के पैटर्न के साथ धैर्य परिवार कार्यों के लिए एक एन-आरी 'अनिश्चित' लिख सकते हैं। 'ZipWithN' का उदाहरण पेपर में दिया गया है "क्या हमें आश्रित प्रकार की आवश्यकता है?"। –

+0

"कोई रास्ता नहीं" शायद थोड़ा बोल्ड था। मैंने अपना जवाब बदल दिया है "कोई सीधा रास्ता नहीं"। –

+0

@stephentetley क्या कार्यान्वयन कहीं भी पैकेज में लागू किया गया है? – CMCDragonkai

11

नकली करने के लिए अतिव्य्घ्र प्रकार प्रणाली चाल का उपयोग कर बात की इस तरह के तरीके ढूँढना मेरे शौक में से एक है, इसलिए मुझ पर भरोसा जब मैं कहता हूँ कि परिणाम बहुत बदसूरत है। विशेष रूप से, ध्यान दें कि tuples को पुनरावर्ती रूप से परिभाषित नहीं किया गया है, इसलिए सीधे उन पर अमूर्त करने का कोई वास्तविक तरीका नहीं है; जहां तक ​​हास्केल की टाइप सिस्टम का संबंध है, हर ट्यूपल आकार पूरी तरह से अलग है।

सीधे टुपल्स के साथ काम करने के लिए कोई व्यवहार्य दृष्टिकोण इसलिए कोड पीढ़ी की आवश्यकता होगी - या तो TH12 या tuple पैकेज के साथ बाहरी उपकरण का उपयोग करना।

यह नकली करने के लिए

उत्पन्न कोड का उपयोग किए बिना, आप पुनरावर्ती परिभाषाओं का उपयोग करने के लिए पहली रिसॉर्ट के लिए है - एक "शून्य" मूल्य के साथ आम तौर पर सही-नेस्टेड जोड़े, अंत बताने के लिए या तो (,) और () या कुछ और करने के लिए उन्हें बराबर। आप देख सकते हैं कि इस (:) और [] के मामले में सूचियों की परिभाषा के समान --और वास्तव में, रिकर्सिवली परिभाषित इस तरह के छद्म-tuples किसी भी प्रकार के स्तर के डेटा संरचनाओं के रूप में देखा जा सकता है (प्रकार की एक सूची) या के रूप में है विषम सूचियां (उदाहरण के लिए, एचएलआईस्ट इस तरह से काम करता है)।

कमियां शामिल हैं, लेकिन, तथ्य यह है कि वास्तव में चीजों का निर्माण इस तरह से उपयोग करते हुए अधिक परेशान करने की तुलना में यह लायक है हो सकता है, कोड प्रकार प्रणाली चाल लागू करने के लिए ही सीमित नहीं हैं आमतौर पर चौंकाने और पूरी तरह से गैर पोर्टेबल है, और अंतिम परिणाम किसी भी तरह के बराबर नहीं है - उदाहरण के लिए (a, (b, (c,()))) और (a, b, c) के बीच कई नॉनट्रिविअल अंतर हैं।

यदि आप देखना चाहते हैं कि यह कितना भयानक हो जाता है तो आप the stuff I have on GitHub पर विशेष रूप से बिट्स here देख सकते हैं।