2016-06-19 13 views
3

Рассмотрим следующий код:Как работает `valueB`? Он всегда возвращает одно и то же значение?

module Main where 

import Control.Event.Handler 
import Reactive.Banana 
import Reactive.Banana.Frameworks 

main :: IO() 
main = do 
    (addHandler, fire) <- newAddHandler 
    compile (network addHandler) >>= actuate 
    fire "fire one" 
    fire "fire two" 

network :: AddHandler String -> MomentIO() 
network addHandler = do 
    fireEvent <- fromAddHandler addHandler 
    behavior <- stepper "initial stepper value" fireEvent 
    behaviorValue <- valueB behavior 
    reactimate $ putStrLn . (\v -> "fire input: " ++ show v) <$> fireEvent 
    reactimate $ print behaviorValue <$ fireEvent 

Выход из этой программы:

fire input: "fire one" 
"initial stepper value" 
fire input: "fire two" 
"initial stepper value" 

Могу ли я с помощью valueB правильно? Если нет, что я делаю неправильно? Какова цель valueB и когда я должен ее использовать?

ответ

2

Это помогает иметь в виду, что монада MomentMomentIO) выражает вычисление, которое происходит в определенный момент времени. Комбинатор valueB просто возвращает значение Поведения в тот момент. В вашем случае это в самом начале.

Если вы хотите попробовать значение поведения в разное время, вы можете использовать <@> и <@ операторов, которые очень похожи на <$> и <$. Например, заменив последнюю строку с

reactimate $ print <$> behavior <@ fireEvent 

напечатает значение поведения в каждый момент, когда срабатывает событие.

Более совершенным использованием было бы использование valueB с execute.

+0

В конце концов я понял, что 'valueB' находится в разделе« более высокого порядка »документации по какой-либо причине и, вероятно, чаще всего встречается в сочетании с другими операциями более высокого порядка, такими как' switchB'. Это верно? – Buttons840

+1

@ Buttons840 Да, точно. :-) –

1

Согласно документации, valueB получает текущее значение данного поведения. Он работает примерно в MonadMoment. В этом случае этот «момент» - это время создания сети. По этой причине вы всегда получаете одинаковое значение. Вы запрашиваете значение только один раз, в начале.

Вы не можете напрямую реагировать на изменения в Behaviors, так как они действительно не сообщают об их изменениях (они являются непрерывными сигналами).

Если вы хотите увидеть valueB в действии. Я думаю, что функция execute - это то, что вам нужно.

execute (valueB <$> stepper "initial stepper value" fireEvent) 

Это, конечно, очень надуманный пример, но он должен делать то, что вы хотите.

Кроме того, у меня нет опыта работы с ReactiveBanana, но большинство структур FRP работают аналогично.