2013-11-27 8 views
1

Sodium의 기능적 반응 형 프로그래밍 모델이 어떻게 작동하는지 이해하려고 노력 중이며 일부 장애가 있습니다. "Time"값으로 업데이트 할 숫자 목록이 있는데 공백 문자가 전달되면이 목록에 추가됩니다. 실행 엔진은 다음과 같습니다.Sodium 이벤트 업데이트 반영되지 않음

import FRP.Sodium 

type Time = Event Int 
type Key = Event Char 
type Game a = Time -> Key -> Reactive (Behavior a) 

run :: Show a => Game a -> IO() 
run game = do 
    (dtEv, dtSink) <- sync newEvent 
    (keyEv, keySink) <- sync newEvent 
    g <- sync $ do 

     game' <- game dtEv keyEv 
     return game' 

    go g dtSink keySink 
    return() 
    where 
    go gameB dtSink keySink = do 
     sync $ dtSink 1 

     ks <- getLine 
     mapM_ (sync . keySink) ks 

     v <- sync $ sample gameB 
     print v 

     go gameB dtSink keySink 

그래서 여기서는 게임 동작이 모든 "틱"에주는 현재 값을 인쇄하고 있습니다. 다음은 게임 동작에 대한 코드입니다. 나는이 뭘 기대하는 무엇

main :: IO() 
main = run game 


game :: Time -> Key -> Reactive (Behavior [Int]) 
game dt key = do 
    let spawn = const 0 <$> filterE (==' ') key 

    rec 
     bs <- hold [] $ snapshotWith (\s xs -> (s:xs)) spawn updated 

     updated <- hold [] $ snapshotWith (\t xs -> map (+t) xs) dt bs 


    return updated 

0이 목록에 주입됩니다, 입력 된 모든 공백 문자와 함께입니다. Enter를 누를 때마다 목록의 모든 숫자가 하나씩 증가 할 것으로 예상됩니다. 대신에 숫자를 증가 시키려면 공간을 눌러야합니다. 어디서 잘못 알 수 있습니까?

답변

1

좀 더 생각해 보면, 문제가 무엇인지 꽤 분명합니다. 내 코드의 문제는 각 순환 동작이 자체 변경 내용에 따라 다르다는 사실을 고려하지 않은 순환 의존성입니다. 이것은 내가 목록에 추가하려고 할 때마다 시간 값이 변경 될 때까지 값을 변경하기 위해 시간 업데이트에 의해 주어진 목록의 이전 값을 취할 것이라는 것을 의미했습니다. 이 문제를 바로 잡기 위해 game 동작을 재구성하여 업데이트와 병합 이벤트를 병합했습니다.

data GEvent = Alter ([Int] -> [Int]) 

game :: Time -> Key -> Reactive (Behavior [Int]) 
game dt key = do 
    let spawn = const (Alter (\xs -> (0:xs))) <$> filterE (==' ') key 
     update = (\t -> Alter (\xs -> map (+t) xs)) <$> dt 
     applyAlter (Alter f) xs = f xs 

    rec 
     bs <- hold [] $ snapshotWith applyAlter (merge spawn update) bs 


    return bs 

이렇게하면 두 가지 이벤트 중 하나가 발생하면 가장 최신 버전의 목록을 가져옵니다.