2015-05-02 5 views
2

Я бы обновил поведение (Cell/Val) от его текущего значения.рекурсивное обновление «Поведение» в потоке урожая натрия заблокировано ...

, но следующий код выдает поток, заблокированный на неопределенный срок при операции MVar. исключение.

Я ожидал, что он напечатает три раза значение i: '. что я пропустил? - благодаря.

{-# LANGUAGE RecursiveDo #-} 
    module Main where 

    import   FRP.Sodium 

    main :: IO() 
    main = do 
    (e, t) <- sync newEvent 

    rec 
     b <- sync $ hold 0 $ snapshot (\_ i -> i + 1) e b 

    sync $ listen (value b) (\i -> putStrLn $ "value of i: " ++ show i) 

    sync $ t "ping" 
    sync $ t "ping" 
    sync $ t "ping" 

    return() 

  • GHCi, версия 7.8.3
  • натрия-0.11.0.3

ответ

2

Ваш рекурсивный пусть из RecursiveDo находится в IO монады. Монада Reactive также имеет экземпляр MonadFix. Вы можете полностью определить b в пределах Reactive, а затем использовать sync вокруг этого, чтобы выполнить все определение как транзакцию.

main = do 
    (e, t) <- sync newEvent 

    b <- sync $ 
     do 
      rec 
       b <- hold 0 $ snapshot (\_ i -> i + 1) e b 
      return b 

    sync $ listen (value b) (\i -> putStrLn $ "value of i: " ++ show i) 

    ... 

Обозначение RecursiveDo не помогает на примере этого простого. То же самое можно записать легче с точки зрения mfix.

main = do 
    (e, t) <- sync newEvent 

    b <- sync . mfix $ hold 0 . snapshot (\_ i -> i + 1) e 

    sync $ listen (value b) (\i -> putStrLn $ "value of i: " ++ show i) 

    ... 

Это, вероятно, стоит отметить, что создание Behavior из Event обычно делается с accum.

b <- sync $ accum 0 (const (+1) <$> e) 

В натрия это производная функция и внутренне определены в терминах hold, snapshot и mfix.

accum :: Context r => a -> Event r (a -> a) -> Reactive r (Behavior r a) 
accum z efa = do 
    rec 
     s <- hold z $ snapshot ($) efa s 
    return s