Haskell Language
रिएक्टिव-केला
खोज…
पुस्तकालय में बाहरी घटनाओं का इंजेक्शन लगाना
यह उदाहरण किसी भी ठोस GUI टूलकिट से बंधा नहीं है, उदाहरण के लिए प्रतिक्रियाशील-केला-डब्ल्यूएक्स करता है। इसके बजाय यह दिखाता है कि एफआरपी मशीनरी में मनमानी IO क्रियाओं को कैसे इंजेक्ट किया जाए।
Control.Event.Handler मॉड्यूल एक addHandler फ़ंक्शन प्रदान करता है जो AddHandler a और a -> IO () मानों की एक जोड़ी बनाता है। पूर्व का उपयोग प्रतिक्रियाशील-केला द्वारा स्वयं किसी Event a मान प्राप्त करने के लिए किया जाता है, जबकि बाद वाला एक सादा फ़ंक्शन है जिसका उपयोग संबंधित ईवेंट को ट्रिगर करने के लिए किया जाता है।
import Data.Char (toUpper)
import Control.Event.Handler
import Reactive.Banana
main = do
(inputHandler, inputFire) <- newAddHandler
हमारे मामले में हैंडलर का a पैरामीटर टाइप String , लेकिन कोड जो कंपाइलर का पता लगाता है जो बाद में लिखा जाएगा।
अब हम EventNetwork को परिभाषित करते हैं जो हमारे FRP- संचालित प्रणाली का वर्णन करता है। यह compile फ़ंक्शन का उपयोग करके किया जाता है:
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
inputEvent <- fromAddHandler inputHandler
fromAddHandler फ़ंक्शन AddHandler a को एक Event a में AddHandler a मान में बदल देता Event a , जो अगले उदाहरण में कवर किया गया है।
अंत में, हम अपना "इवेंट लूप" लॉन्च करते हैं, जो उपयोगकर्ता इनपुट पर घटनाओं को आग लगाएगा:
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
...
forever $ do
input <- getLine
inputFire input
घटना प्रकार
प्रतिक्रियाशील-केले में Event प्रकार समय में कुछ घटनाओं की एक धारा का प्रतिनिधित्व करता है। एक Event इस अर्थ में एक एनालॉग आवेग संकेत के समान है कि यह समय में निरंतर नहीं है। नतीजतन, Event का एक उदाहरण है Functor केवल typeclass। आप दो Event एक साथ जोड़ नहीं सकते क्योंकि वे अलग-अलग समय पर आग लगा सकते हैं। आप Event के [वर्तमान] मान के साथ कुछ कर सकते हैं और कुछ IO क्रिया के साथ उस पर प्रतिक्रिया कर सकते हैं।
Event मान पर रूपांतरणों को fmap का उपयोग करके किया जाता है:
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
inputEvent <- fromAddHandler inputHandler
-- turn all characters in the signal to upper case
let inputEvent' = fmap (map toUpper) inputEvent
किसी Event पर प्रतिक्रिया उसी तरह से की जाती है। पहले आप इसे टाइप fmap a -> IO () की कार्रवाई के साथ और फिर इसे reactimate फ़ंक्शन में पास करें:
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
inputEvent <- fromAddHandler inputHandler
-- turn all characters in the signal to upper case
let inputEvent' = fmap (map toUpper) inputEvent
let inputEventReaction = fmap putStrLn inputEvent' -- this has type `Event (IO ())
reactimate inputEventReaction
अब जब भी inputFire "something" कहा जाता है, "SOMETHING" inputFire "something" मुद्रित किया जाएगा।
व्यवहार प्रकार
महाद्वीपीय संकेतों का प्रतिनिधित्व करने के लिए, प्रतिक्रियाशील-केला Behavior a प्रकार का Behavior a । विपरीत Event , एक Behavior एक है Applicative , आप गठबंधन एन की सुविधा देता है जो Behavior एक n-ary शुद्ध समारोह का उपयोग कर s (का उपयोग कर <$> और <*> )।
एक प्राप्त करने के लिए Behavior a से Event a है accumE समारोह:
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
...
inputBehavior <- accumE "" $ fmap (\oldValue newValue -> newValue) inputEvent
accumE Behavior के प्रारंभिक मूल्य और एक Event लेता है, जिसमें एक फ़ंक्शन होता है जो इसे नए मूल्य पर सेट करेगा।
Event एस के साथ, आप वर्तमान Behavior मान के साथ काम करने के लिए fmap का उपयोग कर सकते हैं, लेकिन आप उन्हें (<*>) भी जोड़ सकते हैं।
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
...
inputBehavior <- accumE "" $ fmap (\oldValue newValue -> newValue) inputEvent
inputBehavior' <- accumE "" $ fmap (\oldValue newValue -> newValue) inputEvent
let constantTrueBehavior = (==) <$> inputBehavior <*> inputBehavior'
Behavior परिवर्तन पर प्रतिक्रिया करने के लिए एक changes कार्य है:
main = do
(inputHandler, inputFire) <- newAddHandler
compile $ do
...
inputBehavior <- accumE "" $ fmap (\oldValue newValue -> newValue) inputEvent
inputBehavior' <- accumE "" $ fmap (\oldValue newValue -> newValue) inputEvent
let constantTrueBehavior = (==) <$> inputBehavior <*> inputBehavior'
inputChanged <- changes inputBehavior
केवल बात यह है कि ध्यान दिया जाना चाहिए कि है changes लौट Event (Future a) के बजाय Event a । इस वजह से, reactimate' के बजाय प्रयोग किया जाना चाहिए reactimate । इसके पीछे का तर्क प्रलेखन से प्राप्त किया जा सकता है।
EventNetworks को सक्रिय करना
EventNetwork compile द्वारा लौटाए जाने से पहले पुन: सक्रिय होने वाली घटनाओं का प्रभाव होना चाहिए।
main = do
(inputHandler, inputFire) <- newAddHandler
eventNetwork <- compile $ do
inputEvent <- fromAddHandler inputHandler
let inputEventReaction = fmap putStrLn inputEvent
reactimate inputEventReaction
inputFire "This will NOT be printed to the console!"
actuate eventNetwork
inputFire "This WILL be printed to the console!"