2011-10-21 11 views
15

हम इस तरह कोड है:नेटवर्क में प्रतिक्रियाशील-केला हैंडल चक्र कर सकते हैं?

guiState :: Discrete GuiState 
guiState = stepperD (GuiState []) $ 
    union (mkGuiState <$> changes model) evtAutoLayout 

evtAutoLayout :: Event GuiState 
evtAutoLayout = fmap fromJust . filterE isJust . fmap autoLayout $ changes guiState 

आप देख सकते हैं evtAutoLayout guiState जो evtAutoLayout में फ़ीड में फ़ीड - तो वहाँ एक चक्र है। यह जानबूझकर है। ऑटो लेआउट गुई राज्य को तब तक समायोजित करता है जब तक यह संतुलन तक नहीं पहुंच जाता है और फिर यह कुछ भी नहीं देता है और इसलिए इसे लूप को रोकना चाहिए। एक नया मॉडल परिवर्तन बेशक इसे फिर से लात मार सकता है।

जब हम इसे एक साथ रखते हैं, हालांकि, हम संकलन फ़ंक्शन कॉल पर एक अनंत लूप में भागते हैं। यहां तक ​​कि अगर autoLayout = कुछ भी नहीं, यह अभी भी संकलन के दौरान एक ढेर ओवरफ्लो में परिणाम।

अगर मैं guiState में संघ कॉल को हटाने और तस्वीर से बाहर evtAutoLayout को दूर ...

guiState :: Discrete GuiState 
guiState = stepperD (GuiState []) $ mkGuiState <$> changes model 

यह ठीक काम करता है।

कोई सुझाव?

उत्तर

15

सवाल

प्रतिक्रियाशील-केला पुस्तकालय समर्थन रिकर्सिवली परिभाषित घटनाओं करता है?

में केवल एक ही नहीं है, लेकिन तीन जवाब हैं। संक्षिप्त उत्तर हैं: 1. आम तौर पर नहीं, 2. कभी-कभी हां, 3. वर्कअराउंड हां के साथ।

यहां लंबे उत्तरों।

  1. प्रतिक्रियाशील-केले के शब्दों करना का समर्थन नहीं ही के मामले में सीधे एक Event को परिभाषित।

    यह एक निर्णय है कि कोनल इलियट ने अपने मूल एफआरपी अर्थशास्त्र में बनाया और मैंने इसे चिपकने का फैसला किया है। इसका मुख्य लाभ यह है कि अर्थ विज्ञान बहुत ही सरल रहते हैं तो आप हमेशा की

    type Behavior a = Time -> a 
    type Event a = [(Time,a)] 
    

    मैं एक मॉड्यूल Reactive.Banana.Model कि लगभग ठीक इस मॉडल को लागू करता है प्रदान की है मामले में सोच सकते हैं, आप अर्थ विज्ञान के विषय में किसी भी सवाल के लिए अपने स्रोत कोड से परामर्श कर सकते हैं प्रतिक्रियाशील केले के। विशेष रूप से, आप इसे अपने उदाहरण के कारण के लिए उपयोग कर सकते हैं: पेन & पेपर के साथ गणना या जीएचसीआई (कुछ नकली डेटा के साथ) में यह कोशिश करने से आपको पता चलेगा कि evtAutoLayout मान _|_ के बराबर है, यानी अपरिभाषित।

    उत्तरार्द्ध आश्चर्यजनक हो सकता है, लेकिन जैसा कि आपने लिखा है, उदाहरण वास्तव में अनिर्धारित है: जीयूआई स्थिति केवल तभी बदलती है जब evtAutoLayout घटना होती है, लेकिन यह केवल तभी हो सकता है जब आप जानते हों कि जीयूआई राज्य बदलता है, जो बदले में , आदि। द्वारा थोड़ी देर देरी डालने पर आपको हमेशा अजीब फीडबैक लूप को तोड़ने की आवश्यकता होती है। दुर्भाग्यवश, प्रतिक्रियाशील-केले वर्तमान में छोटी देरी डालने का कोई तरीका नहीं प्रदान करता है, मुख्य रूप से क्योंकि मुझे नहीं पता कि [(Time,a)] मॉडल के संदर्भ में छोटी देरी का वर्णन कैसे किया जाता है जिससे रिकर्सन की अनुमति मिलती है। (लेकिन उत्तर 3 देखें।)

  2. को Behavior के संदर्भ में Event परिभाषित करना संभव है और फिर से ईवेंट को संदर्भित करता है। दूसरे शब्दों में, जब तक आप एक व्यवहार के माध्यम से जाते हैं, तब तक रिकर्सन की अनुमति है।

    एक साधारण उदाहरण

    import Reactive.Banana.Model 
    
    filterRising :: (FRP f, Ord a) => Event f a -> Event f a 
    filterRising eInput = eOutput 
        where 
        eOutput = filterApply (greater <$> behavior) eInput 
        behavior = stepper Nothing (Just <$> eOutput) 
    
        greater Nothing _ = True 
        greater (Just x) y = x < y 
    
    example :: [(Time,Int)] 
    example = interpretTime filterRising $ zip [1..] [2,1,5,4,8,9,7] 
    -- example = [(1.0, 2),(3.0, 5),(5.0, 8),(6.0, 9)] 
    

    होगा एक घटना धारा को देखते हुए समारोह filterRising रिटर्न केवल उन घटनाओं है कि पहले लौटे से अधिक है। यह documentation for the stepper function में संकेत दिया गया है।

    हालांकि, यह शायद आपकी पसंद की पुनरावृत्ति की तरह नहीं है।

  3. फिर भी, प्रतिक्रियाशील केले में छोटी देरी डालना संभव है, यह कोर लाइब्रेरी का हिस्सा नहीं है और इसलिए किसी भी गारंटीकृत अर्थशास्त्र के साथ नहीं आता है। साथ ही, आपको ऐसा करने के लिए अपने ईवेंट लूप से कुछ समर्थन की आवश्यकता है।

    उदाहरण के लिए, आप वर्तमान में संभालने के बाद एक घटना को ठीक करने के लिए WxTimer का उपयोग कर सकते हैं। Wave.hs उदाहरण प्रतिक्रियाशील केले के साथ wxTimer के पुनरावर्ती उपयोग को दर्शाता है। मुझे नहीं पता कि क्या होता है जब आप टाइमर अंतराल को 0 पर सेट करते हैं, हालांकि, यह बहुत जल्दी निष्पादित हो सकता है। आपको शायद एक अच्छा समाधान खोजने के लिए थोड़ा सा प्रयोग करना होगा।

आशा है कि मदद करता है; स्पष्टीकरण, उदाहरण इत्यादि के लिए पूछने में संकोच न करें

प्रकटीकरण: मैं प्रतिक्रियाशील-केले पुस्तकालय का लेखक हूं।

+0

चूंकि आपने कहा था कि मैं स्पष्टीकरण/उदाहरणों के लिए पूछ सकता हूं ... आपके फ़िल्टर में, राइजिंग के लिए पहला पैरामीटर क्या है? यदि यह सिर्फ एक ईवेंट और इवेंट को परिवर्तित कर रहा है, तो इसमें 2 पैरा क्यों हैं? और आप फ़िल्टरराइजिंग का उपयोग कैसे करेंगे? धन्यवाद! – mentics

+0

@taotree: आह, पहला पैरामीटर केवल कुछ प्रकार का प्रारंभिक मूल्य था। मैंने अब वर्णन से मेल खाने के लिए उदाहरण बदल दिया है। 'फ़िल्टरराइजिंग' फ़ंक्शन का उपयोग करना सरल है: यह एक ईवेंट स्ट्रीम को तर्क के रूप में लेता है और परिणामस्वरूप एक नया ईवेंट स्ट्रीम देता है, ताकि आप इसे अपनी पसंद की ईवेंट स्ट्रीम पर लागू कर सकें और एक नया प्राप्त कर सकें। –

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