2012-07-31 26 views
7

मैं आम तौर पर प्रतिक्रियाशील केले और एफआरपी के लिए नया हूं, इसलिए क्षमा करें यदि मुझे कुछ स्पष्ट याद आ रही है।ज़िप को कार्यान्वित करना :: इवेंट टी ए -> इवेंट टी बी -> इवेंट टी (ए, बी)

my project (GDB/MI फ्रंट एंड) के लिए मैं जीयूआई और फ्रंट एंड लॉजिक मॉड्यूल दोनों के लिए प्रतिक्रियाशील केले (संस्करण 0.6.0.0) का उपयोग कर रहा हूं। पूर्व महान काम करता है लेकिन बाद के लिए मुझे स्पष्ट रूप से अतिरिक्त संयोजक की आवश्यकता होती है।

उनमें से एक zipE :: Event t a -> Event t b -> Event t (a, b) है।

zipE :: Event t Int -> Event t String -> NetworkDescription t (Event t (Int, String)) 
zipE ea eb = changes $ (,) <$> stepper 0 ea <*> stepper "" eb 
बेशक

, मैं इस से संतुष्ट नहीं हूं: दुर्भाग्य से, मैं सब के साथ आ सकता है NetworkDescription इकाई changes का उपयोग करता है और घटना प्रकार में साधारण नहीं है में एक समाधान है। इस प्रकार मैं पूछना चाहता था कि changes (जो गैर-जीयूआई उद्देश्यों के लिए उपयोग करने के लिए निराश है) के बिना जेनेरिक ज़िप कार्य को कार्यान्वित करना है।

अन्य प्रयास विफल, उदा। tuples के पहले तत्व में

zipE :: Num a => Event t a -> Event t b -> Event t (a,b) 
zipE ea eb = apply (stepper (0,) ((,) <$> ea)) eb 

परिणाम एक के बाद स्थानांतरित किया जा रहा है - मैं "कुछ देरी" stepper द्वारा शुरू की वजह से लगता है। लेकिन मुझे नहीं लगता कि stepper (या उस मामले के लिए accumB) के बिना किसी ईवेंट से व्यवहार कैसे प्राप्त करें और मुझे नहीं लगता कि किसी व्यवहार के बिना किसी फ़ंक्शन को फ़ंक्शन कैसे लागू करें। और कुल मिलाकर, मुझे नहीं लगता कि सामान्य प्रकार के मामले में स्टेपर को प्रारंभिक मूल्य कैसे प्रदान किया जाए।

+2

'ea' और' eb' एक ही समय में आग नहीं जा रहे हैं। (यदि आप जानते हैं कि वे एक ही समय में आग लगने जा रहे हैं क्योंकि वे दोनों एक ही अंतर्निहित घटना से व्युत्पन्न हैं, तो शायद अंतर्निहित घटना को दोबारा शुरू करना सबसे अच्छा है।) आप क्या करना चाहते हैं जब कोई आग लगती है और दूसरा ' टी? – dave4420

+0

डेव, आप सही हैं। मुझे अपने इवेंट नेटवर्क के लिए एक अलग डिज़ाइन चाहिए: -/इसे इंगित करने के लिए धन्यवाद। – copton

+2

मुझे वास्तव में एक अलग घटना नेटवर्क की आवश्यकता है।प्रारंभ में, मैं tfles को 'f :: (ए, बी) -> आईओ() 'में खिलाने के लिए दो घटनाओं को ज़िप करना चाहता था। मेरे पास अब इसके बजाय 'f :: a -> b -> IO() 'और' प्रतिक्रिया $ (एफ <$> stepper 0 aE) <@> bE' है। – copton

उत्तर

13

आपको zipE को परिभाषित करने में कठिनाई हो रही है क्योंकि यह अर्थपूर्ण अर्थ नहीं बनाता है। आप अर्थ परिभाषाओं पर विचार करें

Event a == [(Time, a)] 
Event b == [(Time, b)] 

वहाँ, उन्हें ज़िप, क्योंकि सामान्य रूप में प्रत्येक घटना एक अलग समय पर किया जाएगा एक प्राकृतिक तरीका नहीं है।

किसी उत्पाद की बजाय योग का उपयोग करके उन्हें ज़िप करना संभव है।

zipE :: Event a -> Event b -> Event (Either a b) 
zipE aE bE = (Left <$> aE) `mappend` (Right <$> bE) 

तुम सच में एक ही समय में a और b दोनों की आवश्यकता है, तो उपयुक्त समाधान एक Behavior कि एक या अन्य, या विलय कर दिया Either के रूप में ऊपर स्ट्रीम पर जम जाता है बनाने के लिए है।

संपादित करें: मर्ज किए गए स्ट्रीम (अनचाहे) पर जमा करने के एक तरीके का एक उदाहरण। अन्य कार्यान्वयन भी संभव है। यह दोनों घटनाओं को एक ही समय में नहीं बनाता है, बल्कि यह आपको वर्तमान स्थिति को पिछले राज्यों के साथ जोड़ता है ताकि आप हमेशा हाल ही में Left और Right मानों के सबसे हाल ही में उपलब्ध हो सकें।

currentAandB :: a -> b -> Event a -> Event b -> Event (a,b) 
currentAandB a0 b0 aE bE = accumE (a0,b0) (mergefn <$> zipE aE bE) 
    where 
     mergefn (Left a) (_,b) = (a,b) 
     mergefn (Right b) (a,_) = (a,b) 

यह अभी भी दोनों Event धाराओं के लिए प्रारंभिक मान प्रदान करने के लिए आवश्यक है। इस बारे में सोचें: यदि आपके पास केवल Event a से ईवेंट हैं, तो टुपल के दूसरे भाग में क्या मूल्य होना चाहिए?

+0

जॉन, मेरी मदद करने के लिए धन्यवाद। मैं उस उचित उत्तर के बारे में और जानना चाहता हूं जिसका आप उल्लेख कर रहे हैं। क्या आप कृपया विस्तार से बता सकते हैं कि एक या दूसरे पर जमा करने से दोनों घटनाएं एक ही समय में होती हैं? क्षमा करें, अगर यह स्पष्ट है। मैं बस इसे नहीं देखता हूँ। – copton

+1

बिल्कुल मैं क्या सुझाव दूंगा। – Conal

+0

@ कॉपटन: मैंने ऐसा करने के लिए एक तरीके का एक उदाहरण पोस्ट किया है। शुरुआती मूल्यों के लिए, यदि आप अपनी समस्या की प्रारंभिक स्थिति के बारे में सोचते हैं तो आपको शायद एक समझदार उत्तर मिल जाएगा। या आप 'शायद', 'Data.Traversable.sequenceA'' और 'filterJust' के संयोजन का उपयोग केवल आउटपुट उत्पन्न करने के लिए कर सकते हैं जब आपको 'ए' और' बी' दोनों प्राप्त हो जाएं। –

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