2010-07-28 13 views
22

मैं वर्तमान में एक छात्र हूं जो F # का उपयोग कर कार्यात्मक प्रतिक्रियाशील प्रतिमान के बारे में सीख रहा है। यह मेरे लिए मूल रूप से नया दृष्टिकोण है। कल मैंने इस प्रतिमान का उपयोग करके एक साधारण पिंग-पोंग गेम बनाने के बारे में सीखा। मुझे लगता है कि विचार अब तक है: हम समय के कार्यों के रूप में मूल्यों को सोचते हैं। अपने शुद्ध रूप पर, यह स्टेटलेस है। हालांकि, मुझे गेंद (या राज्य) की स्थिति याद रखने की जरूरत है। इसलिए मैं हमेशा वैश्विक कार्य के पैरामीटर के रूप में गेंद की वर्तमान स्थिति को पास करता हूं।कार्यात्मक प्रतिक्रियाशील एफ # - खेलों में राज्यों को संग्रहीत करना

अगर हम थोड़ा और अधिक जटिल खेल के बारे में बात, अंतरिक्ष आक्रमणकारियों की तरह, हम राज्यों के एक बहुत कुछ है (एलियंस 'स्थिति, एलियंस' वर्तमान हिमाचल प्रदेश, शेष बम की संख्या, आदि)

वहाँ एक सुरुचिपूर्ण/सबसे अच्छा है इस समस्या से निपटने का तरीका? क्या हम हमेशा राज्यों को शीर्ष स्तर पर स्टोर करते हैं? क्या सभी मौजूदा राज्यों को वैश्विक कार्य के अतिरिक्त इनपुट तर्क के रूप में दिया जाना चाहिए?

क्या कोई इसे F # पर सरल नमूना का उपयोग करके समझा सकता है? बहुत बहुत धन्यवाद।

उत्तर

13

एफआरपी करने के एक से अधिक तरीके हैं, और यह अनुसंधान का एक सक्रिय क्षेत्र है। सबसे अच्छा क्या है इस बात पर निर्भर करता है कि चीजें एक दूसरे के साथ कैसे बातचीत करती हैं, और भविष्य में नई और बेहतर तकनीकें दिखाई दे सकती हैं।

व्यापक रूप से विचार उन व्यवहारों के लिए है जो सामान्य मूल्यों के अनुसार समय के कार्य होते हैं (जैसा कि आपने कहा था)। व्यवहार अन्य व्यवहारों के संदर्भ में परिभाषित किया जा सकता है, और जब विशेष घटनाएं होती हैं तो अन्य व्यवहारों के बीच स्वैप करने के लिए परिभाषित किया जा सकता है।

आपके उदाहरण में, आपको आमतौर पर तर्क के माध्यम से गेंद की स्थिति को याद रखने की आवश्यकता नहीं होगी (लेकिन कुछ प्रकार के एफआरपी के लिए आप कर सकते हैं)।इसके बजाय आप केवल एक व्यवहार कर सकते हैं:
ballPos : time -> (float * float)
इसमें वैश्विक दायरा हो सकता है, या एक बड़े कार्यक्रम के लिए उस दायरे में इसके सभी उपयोगों के साथ स्थानीय क्षेत्र होना बेहतर हो सकता है।

जैसे चीजें अधिक जटिल हो जाती हैं, आपके पास व्यवहारों को तेजी से जटिल तरीकों से परिभाषित किया जाएगा, अन्य व्यवहारों और घटनाओं पर निर्भर करता है - जिसमें विभिन्न एफआरपी ढांचे में अलग-अलग संभाला जाता है। रिकर्सिव निर्भरताओं के लिए एफ # में मुझे उम्मीद है कि आपको सभी शामिल व्यवहार सहित let rec की आवश्यकता होगी। ये अभी भी संरचनाओं में आयोजित किया जा सकता - शीर्ष-स्तर पर आप हो सकता है:

type alienInfo = { pos : float*float; hp : float } 
type playerInfo = { pos : float*float; bombs : int } 
let rec aliens : time -> alienInfo array =    // You might want laziness here. 
    let behaviours = [| for n in 1..numAliens -> 
         (alienPos player n, alienHP player n) |] 
    fun t -> [| for (posBeh, hpBeh) in behaviours -> 
       {pos=posBeh t; hp=hpBeh t} |]   // You might want laziness here. 
and player : time -> playerInfo = fun t -> 
    { pos=playerPos aliens t; bombs=playerBombs aliens t} 

और फिर alienPos के लिए व्यवहार, alienHP प्लेयर पर निर्भरता, और playerPos साथ, परिभाषित किया जा सकता, playerBombs परिभाषित किया जा सकता एलियंस पर निर्भरता के साथ।

वैसे भी, यदि आप किस प्रकार का एफआरपी उपयोग कर रहे हैं, इसके बारे में अधिक जानकारी दे सकते हैं, तो अधिक विशिष्ट सलाह देना आसान होगा। (और यदि आप किस तरह की सलाह चाहते हैं - व्यक्तिगत रूप से मैं पढ़ने की सिफारिश करता हूं: http://conal.net/papers/push-pull-frp/push-pull-frp.pdf)

6

मुझे एफ # के तहत प्रतिक्रियाशील प्रोग्रामिंग के साथ कोई अनुभव नहीं मिला है, लेकिन पूरी तरह से कार्यात्मक प्रणालियों में वैश्विक स्थिति की समस्या काफी आम है और इसमें काफी सुरुचिपूर्ण समाधान है: मोनाड्स

जबकि मोनैड स्वयं मुख्य रूप से हास्केल में उपयोग किए जाते हैं, अंतर्निहित अवधारणा इसे F # में computation expressions के रूप में बनाती है।

विचार यह है कि आप वास्तव में राज्यों को नहीं बदलते हैं बल्कि राज्य के संक्रमणों का वर्णन करते हैं, यानी नए राज्यों का उत्पादन कैसे करें। राज्य प्रोग्राम में पूरी तरह छुपाया जा सकता है। विशेष monadic वाक्यविन्यास का उपयोग करके, आप लगभग लेकिन अनिवार्य रूप से शुद्ध लेकिन राज्यव्यापी प्रोग्राम लिख सकते हैं।

this source से एक (संशोधित) कार्यान्वयन लेते हुए State इकाई इस

let (>>=) x f = 
    (fun s0 -> 
     let a,s = x s0  
     f a s)  
let returnS a = (fun s -> a, s) 

type StateBuilder() = 
    member m.Delay(f) = f() 
    member m.Bind(x, f) = x >>= f 
    member m.Return a = returnS a 
    member m.ReturnFrom(f) = f 

let state = new StateBuilder()  

let getState = (fun s -> s, s) 
let setState s = (fun _ ->(),s) 

let runState m s = m s |> fst 

तो दिखाई दे सकता है चलो एक उदाहरण है: (सिर्फ एक सूची हम एक समारोह है कि एक लॉग में मान लिख सकते हैं लिखना चाहते हैं) आगे बढ़ते समय। इसलिए हम

let writeLog x = state { 
    let! oldLog = getState // Notice the ! for monadic computations (i.e. where the state is involved) 
    do! setState (oldLog @ [x]) // Set new state 
    return() // Just return(), we only update the state 
} 

परिभाषित state के भीतर, हम अब यह एक अनिवार्य वाक्य रचना में मैन्युअल रूप से लॉग सूची को संभालने के लिए बिना उपयोग कर सकते हैं।

let test = state { 
    let k = 42 
    do! writeLog k // It's just that - no log list we had to handle explicitly 
    let b = 2 * k 
    do! writeLog b 
    return "Blub" 
} 

let (result, finalState) = test [] // Run the stateful computation (starting with an empty list) 
printfn "Result: %A\nState: %A" result finalState 

फिर भी, यहाँ सब कुछ पूरी तरह कार्यात्मक है;)

+0

यह ज्यादातर राज्य मोनड के बारे में है। कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग में अक्सर मोनैड शामिल होते हैं, लेकिन आमतौर पर यह सामान्य प्रकार का राज्य मोनड नहीं होता है। – RD1

+0

जैसा कि मैंने कहा, मुझे एफआरपी में अनुभव नहीं मिला है। फिर भी राज्य मोनड (या बिल्कुल मोनैड) अवधारणा प्रतीत होता है जिसे रेफरेंसियल पारदर्शिता खोने के बिना संदर्भ डेटा को आसानी से संग्रहीत और संशोधित करने के लिए कहा गया है। अगर एफ़टीपी पहले से ही एक monadic बुनियादी ढांचे का उपयोग करता है, तो बेहतर है। एक राज्य मोनैड ट्रांसफॉर्मर को चीज़ बनाना चाहिए (क्या आपका मतलब है कि * सरल प्रकार *?)। लेकिन बुनियादी बातों को समझाए बिना, यह जानकारी बेकार होगी! – Dario

+0

एफआरपी का मुख्य बिंदु व्यवहार के समय के निरंतर कार्यों के रूप में परिभाषित करने की अनुमति दे रहा है - उदा। आप गुरुत्वाकर्षण के तहत जेड (टी) = 9.8 * टी * टी के रूप में एक गेंद की जेड स्थिति को परिभाषित कर सकते हैं। मोनाडिक राज्य केवल राज्य के लिए प्रासंगिक है जो अलग-अलग परिवर्तन करता है - एफआरपी में अलग-अलग बदलावों की भी अनुमति है, लेकिन वे कम केंद्रीय हैं और अक्सर वे एक मोनैड के सटीक रूप में फिट नहीं होते हैं। – RD1

3

टॉमस एफ # में प्रतिक्रियाशील प्रोग्रामिंग के बारे में nice talk दे दी है। आपके मामले में कई अवधारणाओं को लागू करना चाहिए।

+1

कार्यात्मक प्रतिक्रियाशील प्रोग्रामिंग एक कार्यात्मक भाषा में केवल प्रतिक्रियाशील प्रोग्रामिंग की तुलना में काफी कुछ है। मुख्य तकनीक समय के कार्यों के रूप में व्यवहार का प्रतिनिधित्व कर रही है। ये व्यवहार एक दूसरे पर और घटनाओं पर निर्भर कर सकते हैं। तो यह बात इतनी प्रासंगिक नहीं है - इसमें कुछ प्रासंगिकता है, लेकिन केवल इसलिए कि घटनाएं एफआरपी का एक हिस्सा हैं। (मैं मानता हूं कि यह एक अच्छी बात है हालांकि।) – RD1

0

शायद आप FsReactive पर एक नज़र डालना चाहते हैं।

+6

यह बताते हुए कि एफएसआरएक्टिव कैसे प्रश्न का उत्तर देने में मदद करता है, आपके उत्तर की उपयोगिता में सुधार करेगा। –

0

Elm एक आधुनिक एफआरपी कार्यान्वयन है। गतिशील संग्रह मॉडलिंग के लिए जो अंतरिक्ष आक्रमणकारियों जैसे खेलों में सर्वव्यापी हैं, इसमें तीरलाइज्ड एफआरपी की अवधारणाओं के आधार पर Automaton library शामिल है। आपको निश्चित ही इसे परखना चाहिए।

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