2012-02-08 14 views
6

यदि आप अपनी कुंजी के रूप में सूची के प्रत्येक तत्व की (अंतर्निहित) इंडेक्स पर विचार करते हैं, तो zipWith एक संबंधपरक आंतरिक शामिल होने जैसा है। यह केवल कुंजी प्रक्रियाओं दोनों आदानों जिसके लिए मान हैं:कैनोनिकल बाहरी ज़िप कार्य में शामिल हों

zipWith (+) [1..5] [10..20] == zipWith (+) [1..11] [10..14] == [11,13,15,17,19] 

वहाँ एक विहित इसी समारोह में शामिल होने के बाहरी करने के लिए इसी है? कुछ की तरह:

outerZipWith :: (a -> b -> c) -> a -> b -> [a] -> [b] -> [c] 
outerZipWith _ _ _ [] [] = [] 
outerZipWith f a' b' [] (b:bs) = f a' b : outerZipWith f a' b' [] bs 
outerZipWith f a' b' (a:as) [] = f a b' : outerZipWith f a' b' as [] 
outerZipWith f a' b' (a:as) (b:bs) = f a b : outerZipWith f a' b' as bs 

या शायद

outerZipWith' :: (a -> b -> c) -> Maybe a -> Maybe b -> [a] -> [b] -> [c] 
outerZipWith' _ _ _ [] [] = [] 
outerZipWith' _ Nothing _ [] _ = [] 
outerZipWith' _ _ Nothing _ [] = [] 
outerZipWith' f a' b' [] (b:bs) = f (fromJust a') b : outerZipWith f a' b' [] bs 
outerZipWith' f a' b' (a:as) [] = f a (fromJust b') : outerZipWith f a' b' as [] 
outerZipWith' f a' b' (a:as) (b:bs) = f a b : outerZipWith f a' b' as bs 

तो मैं

outerZipWith (+) 0 0 [1..5] [10..20] == [11,13,15,17,19,15,16,17,18,19,20] 
outerZipWith (+) 0 0 [1..11] [10..14] == [11,13,15,17,19,6,7,8,9,10,11] 

कर सकते हैं मैं अपने आप को समय-समय पर यह आवश्यकता होगी, मिल जाए, और मैं नहीं बल्कि एक आम मुहावरा प्रयोग करेंगे outerZipWith को लागू करने के बजाय, या if length as < length bs then zipWith f (as ++ repeat a) bs else zipWith f as (bs ++ repeat b) को लागू करने के बजाय मेरे कोड को अधिक लिखने योग्य (और बनाए रखने में आसान) बनाएं।

उत्तर

5

यह अजीब लगता है क्योंकि आप आदिम परिचालनों से निपटने के बजाय अंत तक जाने की कोशिश कर रहे हैं।

सबसे पहले, zipWith अवधारणात्मक रूप से zipmap (uncurry ($)) है। यह एक महत्वपूर्ण बात है, क्योंकि (अन) करी है क्यों zipWith बिल्कुल संभव है। फ़ंक्शन को लागू करने के लिए [a] और [b] के साथ दिए गए सूचियों को देखते हुए [c] टाइप करें, आपको स्पष्ट रूप से प्रत्येक इनपुट में से एक की आवश्यकता है। ऐसा करने के दो तरीके ठीक से दो Applicative सूचियों के उदाहरण हैं, और zipWith उनमें से एक के लिए liftA2 है। (दूसरा उदाहरण मानक है, जो कार्टेशियन उत्पाद देता है - यदि आप चाहें तो एक क्रॉस जॉइन)।

आप जो अर्थशास्त्र चाहते हैं वह किसी भी स्पष्ट Applicative उदाहरण से मेल नहीं खाते हैं, यही कारण है कि यह अधिक कठिन है। पहले outerZip :: [a] -> [b] -> [?? a b] पर विचार करें और यह किस प्रकार होगा। परिणाम सूची के तत्व प्रत्येक a, b, या दोनों हो सकते हैं। यह न केवल किसी मानक डेटा प्रकार से मेल खाता है, यह उनके संदर्भ में व्यक्त करने के लिए अजीब है क्योंकि आप (A + B + A*B) अभिव्यक्ति से उपयोगी कुछ भी कारक नहीं बना सकते हैं।

इस प्रकार के डेटा प्रकार का अपना उपयोग होता है, यही कारण है कि मेरे पास my own package defining one है। मुझे याद है कि हैकेज पर भी एक है (मेरे विचार से कम सहायक कार्यों के साथ, मुझे लगता है) लेकिन मुझे याद नहीं है कि इसे क्या कहा जाता था।

केवल मानक सामान से चिपके हुए, आपको एक समझदार "डिफ़ॉल्ट मान" की आवश्यकता होती है जो लगभग Monoid उदाहरण और सूचियों को पैड करने के लिए पहचान मान का उपयोग करके अनुवाद करता है। newtype रैपर का उपयोग करके उचित Monoid पर और उससे अनुवाद करना या ऐसा हो सकता है कि आपके वर्तमान कार्यान्वयन से कोई आसान न हो।


एक तरफ, सूची सूचकांक के बारे में आपकी टिप्पणी वास्तव में आगे विकसित की जा सकती है; किसी भी Functor कुंजी की समान धारणा के साथ Reader मोनैड, ए.के.ए. के लिए कुंजी से मूल्यों के लिए एक स्पष्ट कार्य isomorphic है। एडवर्ड Kmett, हमेशा के रूप में, इन अमूर्त विचारों को एन्कोडिंग संकुल का एक गुच्छा है, इस मामले में the representable-functors package से इमारत। मददगार हो सकता है, अगर आपको कम से कम शुरू करने के लिए केवल एक दर्जन उदाहरण लिखना नहीं है ...

+1

'बाहरी ज़िप्प :: ए -> बी -> [ए] -> [बी] -> [(ए, बी)] '? – pat

+0

'outerZip :: (a -> c) -> (बी -> डी) -> सी -> डी -> [ए] -> [बी] -> [(सी, डी)]' – Apocalisp

+0

एक समावेशी -या प्रकार (जैसे आपका 'इन') आवश्यक पहला कदम हो सकता है। कम से कम, यह शुरू करने के लिए एक अच्छी जगह है। – rampion

3

निरंतर छोटी सूची को भरने के बजाय, लंबी सूची के अंत तक मूल्यों की एक सूची क्यों न पहुंचें? यह Maybe की आवश्यकता को भी समाप्त करता है क्योंकि सूची खाली हो सकती है (या सीमित लंबाई)।

outerZipWith :: (a -> b -> c) -> [a] -> [b] -> [a] -> [b] -> [c] 
outerZipWith f as bs as' bs' = take n $ zipWith f (as ++ as') (bs ++ bs') 
    where n = max (length as) (length bs) 
+0

यह संकलित नहीं करता है (कम से कम मेरे लिए)। –

+0

@ हडेन ओह। निश्चित – pat

8

बात इस तरह की आ जाती है:

मैं कुछ भी मानक नहीं मिल सकता है, लेकिन लाइनों आप से पता चला है साथ zipWith की एक पूरी फिर से कार्यान्वयन की कमी, मैं इस तरह अपने length परीक्षण संस्करण विकसित बहुत। यह cogroupPACT algebra का संचालन है। जहां मैं काम करता हूं, हम इन तीन परिचालनों को अलग करने के लिए प्रकार वर्गों का उपयोग करते हैं:

  1. zip: संरचनात्मक चौराहे।
  2. align: संरचनात्मक संघ।
  3. liftA2: संरचनात्मक कार्टशियन उत्पाद।

इस पर Paul Chiusano on his blog द्वारा चर्चा की गई है।

+0

कि पॉल चियसैनो ब्लॉग प्रविष्टि सरल और अंतर्दृष्टिपूर्ण है। इसे जोड़ने के लिए धन्यवाद। –

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