수색…


외부 이벤트를 라이브러리에 삽입

이 예제는 예를 들어 reactive-banana-wx와 같은 구체적인 GUI 툴킷과 관련이 없습니다. 대신에 임의의 IO 작업을 FRP 기계에 주입하는 방법을 보여줍니다.

Control.Event.Handler 모듈은 AddHandler aa -> IO () 값 쌍을 만드는 addHandler 함수를 제공합니다. 전자는 반응식 바나나 자체에서 Event a 값을 가져 오는 데 사용되는 반면 후자는 해당 이벤트를 트리거하는 데 사용되는 일반 함수입니다.

import Data.Char (toUpper)

import Control.Event.Handler
import Reactive.Banana

main = do
    (inputHandler, inputFire) <- newAddHandler

이 경우 처리기 a 매개 변수는 String 유형이지만 컴파일러에서 추론 할 수있는 코드는 나중에 작성됩니다.

이제 FRP 기반 시스템을 설명하는 EventNetwork 를 정의합니다. 이것은 compile 함수를 사용하여 수행됩니다 :

main = do
    (inputHandler, inputFire) <- newAddHandler
    compile $ do
        inputEvent <- fromAddHandler inputHandler

fromAddHandler 함수는 AddHandler a 값을 Event a 로 변환합니다. 다음 예제에서 설명합니다.

마지막으로 사용자 입력시 이벤트를 발생시키는 "이벤트 루프"를 시작합니다.

main = do
    (inputHandler, inputFire) <- newAddHandler
    compile $ do
        ...
    forever $ do
        input <- getLine
        inputFire input

이벤트 유형

반응 형 바나나에서 Event 유형은 시간의 일부 이벤트 스트림을 나타냅니다. Event 는 시간적으로 연속적이지 않다는 의미에서 아날로그 임펄스 신호와 유사합니다. 결과적으로 EventFunctor typeclass의 인스턴스입니다. 서로 다른 시간에 발사 할 수 있기 때문에 두 개의 Event 함께 결합 할 수 없습니다. Event 의 [현재] 값으로 무언가를 할 수 있고 IO 동작으로 반응 할 수 있습니다.

Event s 값의 변환은 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 반응하는 것도 같은 방식으로 수행됩니다. 먼저 a -> IO () 유형의 액션으로 fmap 을 수행 한 다음 함수를 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" 이 인쇄됩니다.

행동 유형

지속적인 신호를 표현하기 위해 반응성 바나나 기능 Behavior a 유형. Event 와 달리 BehaviorApplicative 이며 n Behavior 순수 함수 ( <$><*> )를 사용하여 n Behavior 를 결합 할 수 있습니다.

Event a 에서 Behavior a 를 얻으려면 다음과 같이 accumE 함수가 있습니다.

main = do
    (inputHandler, inputFire) <- newAddHandler
    compile $ do
        ...
        inputBehavior <- accumE "" $ fmap (\oldValue newValue -> newValue) inputEvent

accumEBehavior 의 초기 값과 Event 에 새로운 값을 설정하는 함수를 포함합니다.

Event 와 마찬가지로 fmap 을 사용하여 현재 Behavior 값으로 작업 할 수 있지만 (<*>) 와 결합 할 수도 있습니다.

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

주목해야 할 것은 changesEvent a 대신 Event (Future a) 를 반환한다는 것입니다. 이 때문에 반응을 reactimate' 대신에 reactimatereactimate 합니다. 이것에 대한 근거는 문서에서 얻을 수 있습니다.

이벤트 네트워크 작동

EventNetwork 이벤트가 효과를 내기 전에 compile 의해 리턴 된 EventNetwork 가 작동되어야합니다.

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!"


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow