2011-12-21 2 views
17

में व्यवहार (और अन्य प्रकार) को लागू करने के लिए कहां मैं reactive-banana का उपयोग कर प्रोग्राम पर काम कर रहा हूं, और मैं सोच रहा हूं कि बुनियादी प्रकार के एफआरपी बिल्डिंग ब्लॉक के साथ मेरे प्रकारों को कैसे व्यवस्थित किया जाए।एफआरपी

उदाहरण के लिए, यहां मेरे वास्तविक कार्यक्रम से एक सरल उदाहरण है: मेरा सिस्टम मुख्य रूप से विजेट से बना है - मेरे कार्यक्रम में, पाठ के टुकड़े समय के साथ भिन्न होते हैं।

मैं

newtype Widget = Widget { widgetText :: Behavior String } 

हो सकता था लेकिन मैं यह भी

newtype Widget = Widget { widgetText :: String } 

है और Behavior Widget का उपयोग जब मैं समय-अलग व्यवहार के बारे में बात करना चाहता हूँ सकता है। ऐसा लगता है कि चीजें "सरल" बनाती हैं, और इसका मतलब है कि मैं इसे करने के लिए विजेट को अनपैक और रीपैक करने के बजाय Behavior संचालन का अधिक उपयोग कर सकता हूं।

दूसरी ओर, पूर्व कोड है कि वास्तव में विजेट्स को परिभाषित करता है में दोहराव से बचने के, के बाद से लगभग सभी विजेट का समय के साथ बदल रहा है, और मैं अपने आप को भी कुछ है कि Behavior साथ नहीं है परिभाषित, यह बाद से लगता है मैं उन्हें दूसरों के साथ एक अधिक संगत तरीके से गठबंधन करने देता हूं।

एक और उदाहरण के रूप में, दोनों प्रस्तुतियों के साथ, Monoid उदाहरण (और मैं अपने कार्यक्रम में एक होना चाहता हूं) होने का अर्थ है, लेकिन बाद के लिए कार्यान्वयन अधिक प्राकृतिक लगता है (क्योंकि यह केवल एक छोटा सा उठाना है newtype के लिए monoid सूची)।

इसी तरह (मेरे वास्तविक कार्यक्रम नहीं बल्कि Behavior से Discrete का उपयोग करता है, लेकिन मुझे लगता है कि प्रासंगिक है नहीं लगता है।)

, मैं Behavior (Coord,Coord) या (Behavior Coord, Behavior Coord) का उपयोग करना चाहिए एक 2D बिंदु का प्रतिनिधित्व करते हैं? इस मामले में, पूर्व स्पष्ट पसंद की तरह लगता है; लेकिन जब यह पांच-तत्व रिकॉर्ड होता है जो गेम में किसी इकाई की तरह कुछ प्रस्तुत करता है, तो विकल्प कम स्पष्ट लगता है।

संक्षेप में, इन सभी समस्याओं के लिए नीचे को कम:

एफआरपी का उपयोग करते समय क्या परत पर मैं Behavior प्रकार आवेदन करना चाहिए?

(वही सवाल भी Event पर लागू होता है, एक डिग्री कम है, हालांकि।)

उत्तर

5

मैं dflemstr's advice

  1. करने के साथ सहमत पृथक "बात यह है कि बदल जाता है" जितना संभव हो उतना।
  2. समूह "चीजें जो एक साथ बदलती हैं" एक Behavior/Event में।

और अंगूठे के इन नियमों के लिए अतिरिक्त कारण प्रदान करना चाहते हैं।

प्रश्न निम्नलिखित करने पर निर्भर करता: आप मान उस समय में बदल की एक जोड़ी (टपल) का प्रतिनिधित्व करना चाहते हैं और क्या

एक का उपयोग करने के सवाल है। (Behavior x, Behavior y) - व्यवहार की एक जोड़ी

बी। Behavior (x,y) - जोड़े की एक व्यवहार एक दूसरे के ऊपर पसंद करते हैं के लिए

कारण

  • एक से अधिक ख हैं।

    पुश-संचालित कार्यान्वयन में, व्यवहार में परिवर्तन से संबंधित सभी व्यवहारों का पुनर्मूल्यांकन ट्रिगर होगा।

    अब, उन व्यवहारों पर विचार करें जिनके मूल्य केवल युग्म के पहले घटक x पर निर्भर करते हैं। संस्करण में, दूसरे घटक y का परिवर्तन व्यवहार को दोबारा नहीं करेगा। लेकिन वेरिएंट बी में, व्यवहार का पुनर्मूल्यांकन किया जाएगा, भले ही इसका मूल्य दूसरे घटक पर निर्भर न हो। दूसरे शब्दों में, यह बढ़िया अनाज बनाम मोटे अनाज वाली निर्भरताओं का सवाल है।

    इस कोर्स की सलाह 1. के लिए एक तर्क है, यह बहुत महत्व का नहीं है जब दोनों व्यवहार जो पैदावार सलाह 2.

    बेशक

    एक साथ बदल जाते हैं,, पुस्तकालय ठीक पेशकश करने के लिए एक तरह से की पेशकश करनी चाहिए वेरिएंट बी के लिए भी भरोसेमंद निर्भरता। प्रतिक्रियाशील-केला संस्करण 0.4.3 के रूप में, यह संभव नहीं है, लेकिन इसके बारे में चिंता न करें, मेरे पुश-संचालित कार्यान्वयन भविष्य के संस्करणों में परिपक्व होने जा रहा है।

  • बी पर बी।

    यह देखते हुए कि प्रतिक्रियाशील-केला संस्करण 0.4.3 dynamic event switching प्रदान नहीं करता है, कुछ प्रोग्राम हैं जो आप केवल तभी लिख सकते हैं यदि आप सभी घटकों को एक ही व्यवहार में डालते हैं। कैननियल उदाहरण एक प्रोग्राम होगा जिसमें वैरिएबल काउंटरों की संख्या होगी, यानी TwoCounter.hs उदाहरण का विस्तार। आपने अभी तक व्यवहार की एक गतिशील संग्रह का ट्रैक रखने के कोई रास्ता नहीं है क्योंकि वहाँ मूल्यों

    counters :: Behavior [Int] 
    

    का समय बदलते सूची के रूप में यह प्रतिनिधित्व करने के लिए किया है। उस ने कहा, प्रतिक्रियाशील केले के अगले संस्करण में गतिशील घटना स्विचिंग शामिल होगी।

    इसके अलावा, आप हमेशा संस्करण एक से परिवर्तित कर सकते हैं किसी भी मुसीबत

    uncurry (liftA2 (,)) :: (Behavior a, Behavior b) -> Behavior (a,b) 
    
+1

ठीक है, 'विजेट' के मामले में, केवल एक फ़ील्ड होने पर सरलीकरण नहीं था, यह मेरी वास्तविक स्थिति है, इसलिए कोई tuples शामिल नहीं हैं :) मदद के लिए धन्यवाद, हालांकि - यह होना चाहिए भविष्य में बहुत मददगार! मैं अब 'व्यवहार' को नए प्रकार के अंदर रखूंगा। काश मैं दोनों उत्तरों को स्वीकार कर सकता हूँ :) – ehird

6

नियमों का उपयोग मैं जब एफआरपी अनुप्रयोगों के विकास, कर रहे हैं:

  1. "बात यह है कि बदल जाता है" के रूप में अलग जितना संभव हो।
  2. समूह "चीजें जो एक साथ बदलती हैं" एक Behavior/Event में।

कारण (1) का कारण है कि यदि आपके द्वारा उपयोग किए जाने वाले डेटा प्रकार यथासंभव प्राचीन हैं तो अमूर्त संचालन बनाना और रचना करना आसान हो जाता है।

इसका कारण यह है कि Monoid जैसे उदाहरण कच्चे प्रकार के लिए पुन: उपयोग किए जा सकते हैं, जैसा आपने वर्णन किया है।

ध्यान दें कि आप डेटाटाइप की "सामग्री" को आसानी से संशोधित करने के लिए Lenses का उपयोग कर सकते हैं जैसे कि वे कच्चे मूल्य थे, ताकि अतिरिक्त "रैपिंग/अनैपिंग" समस्या न हो। (इस विशेष लेंस कार्यान्वयन के परिचय के लिए this recent tutorial देखें; others हैं)

कारण (2) का कारण यह है कि यह अनावश्यक ओवरहेड को हटा देता है। यदि दो चीजें एक साथ बदलती हैं, तो वे "समान व्यवहार करते हैं", इसलिए उन्हें इस तरह मॉडल किया जाना चाहिए।

Ergo/tl; डॉ: आप क्योंकि (1) के newtype Widget = Widget { widgetText :: Behavior String } का उपयोग करना चाहिए, और आप Behavior (Coord, Coord) का उपयोग करना चाहिए की वजह से (2) (के बाद से दोनों का समन्वय करता है आमतौर पर एक साथ बदल)।

+0

मुझे नहीं लगता कि लेंस यहाँ मदद के बिना संस्करण के लिए - 'Monoid' उदाहरण उपयोग करने के लिए, यह कि 'f = liftA2 mappend' जैसे कुछ' fab = विजेट $ mappend (widgetText a) बन जाता है (विजेटटेक्स्ट बी) '। माना जाता है कि, उठाने वाले संयोजक इस दर्द को कम कर सकते हैं। हालांकि, मुझे यकीन नहीं है कि आप मेरे 'मोनॉयड' उदाहरण का संदर्भ देकर क्या कहने की कोशिश कर रहे हैं - यह 'स्ट्रिंग' फॉर्म के लिए तर्क था, न कि 'व्यवहार स्ट्रिंग' फॉर्म। – ehird

+0

आपके नियम बहुत अच्छे लगते हैं, और मुझे इसके बारे में कुछ और सोचना होगा। इसे पोस्ट करने के लिए धन्यवाद! मैं अभी तक इस जवाब को स्वीकार नहीं करूंगा क्योंकि मैं अन्य विचारों और दृष्टिकोणों को सुनना चाहता हूं और चूंकि यह काफी सूक्ष्म प्रश्न है। – ehird

+0

आपके 'विजेट' उदाहरण में, इसमें केवल' विजेट टेक्स्ट 'होता है जो कच्चे उठाने को छोटा बनाता है। यदि आपके पास 'विजेट' में अधिक मूल्य थे, तो कच्चे उठाने से लेंस के माध्यम से 'व्यवहार' उठाने और इस तरह से संचालन करने से कहीं अधिक जटिल हो जाता है। – dflemstr

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