2012-05-28 3 views
7

Я пишу музыкальный плеер в Haskell с реактивным бананом. Одна из проблем, с которой я сталкиваюсь, - это получение актуальных значений с помощью метода fromPoll. Я хочу, чтобы пользователь мог дополнительно выбрать часть трека во время игры. Мой код выглядит примерно так:Реактивно-банановые: обновленные значения fromPoll

makePlayNetworkDescr :: Player a => AddHandler Command -> a -> NetworkDescription t() 
makePlayNetworkDescr addCmdEvent player = do 
    bPosition <- fromPoll (getPosition player) 
    eCmds <- fromAddHandler addCmdEvent 

    let eSetStart = filterE (isJust) $ bPosition <@ filterE (==SetStart) eCmds 
     eSetEnd = filterE (isJust) $ bPosition <@ filterE (==SetEnd) eCmds 
     eClearRange = filterE (==ClearRange) eCmds 

     bStart = accumB Nothing ((const <$> eSetStart) `union` (const Nothing <$ eClearRange)) 
     bEnd = accumB Nothing ((const <$> eSetEnd) `union` (const Nothing <$ eClearRange)) 

Выше GetPosition является частичной функцией, не возвращая ничего до воспроизведения на самом деле начинается. Проблема в том, что как только addCmdEvent срабатывает в первый раз, bPosition по-прежнему будет содержать Nothing значение. eSetStart/End вычислить их значения на основе этого. Только тогда bPosition обновляется, и это значение, которое будет использоваться в следующий раз, когда addCmdEvent пожаров. И так далее, ценность всегда будет «отключена на один», так сказать.

Существует связанный SO question, но в этом случае существует событие «триггер», которое может использоваться для вычисления нового значения поведения. Есть что-то подобное с помощью Poll?

+0

Когда вы закончите, вы должны поместить результат в Hackage. С нетерпением ждем, чтобы сыграть мою музыку с Haskell! – amindfv

+0

Я планирую однажды поставить его на Hackage (hah). Я закончил. Однако это музыкальный проигрыватель «царапины мой собственный зуд», чтобы помочь с расшифровкой музыки, поэтому я не уверен, насколько интересно было бы другим людям. – oggy

ответ

2

Начиная с реактивного банана-0,5 и 0,6 функция fromPoll обновляет поведение, когда внешнее событие запускает сеть событий. Вы можете получить доступ к этим обновлению, как события, используя

eUpdate <- changes bSomeBehavior 

Однако, обратите внимание, что поведение представляет собой непрерывные нестационарные значения, которые не поддерживают общее понятие «событие обновления». Функция changes попытается вернуть полезное приближение, но официальных гарантий нет.

В качестве альтернативы вы можете изменить внешнее событие, чтобы включить положение игрока как часть addCmdEvent. В вашем случае это означает добавление дополнительных данных в конструкторы SetStart и SetEnd. Затем вы можете использовать

eSetStart = filterJust $ matchSetStart <$> eCmds 
    where 
    matchSetStart (SetStart pos) = Just pos 
    matchSetStart _    = Nothing 

Оба решения требуют, чтобы наблюдать самое последнее значение, как событие, а не поведение. Причина в том, что поведение, созданное с помощью stepper, всегда будет возвращать старое значение в момент их обновления (они «отстают на один»), так как это очень полезно для рекурсивных определений.

В любом случае основной вопрос является то, что позиция игрока обновляется внешне задолго до addCmdEvent происходит, но проблема в том, что это не то, что сеть событие видит. Скорее, сеть считает, что поведение, возвращаемое fromPoll, обновляется одновременно с addCmdEvent. Фактически, если у вас нет доступа к источнику внешних событий, который отвечает за обновление позиции игрока, это единственное, что он может подумать. (Если у вас есть доступ, вы можете использовать функцию .)

Я понимаю, что такое поведение fromPoll несколько неудовлетворительно для вашего общего использования. Я не определился, должен ли я исправить это в своей библиотеке: есть компромисс между fromPoll, возвращающим последнее значение, и функцию changes, пытающуюся сделать все возможное.Если последнее значение возвращается, то будет вести себя так, как если бы оно пропустило одно обновление (когда значение было обновлено извне) и вызвало избыточное (когда сеть обновляет значение, соответствующее внешнему). Если у вас есть мнение по этому поводу, сообщите мне.


Обратите внимание, что сочетание поведения с аппликативным оператором <*> будет сочетать в себе самый последние значения просто отлично.

+0

Спасибо за ответ. В конце концов я пошел по пути опроса данных позиции извне и включил его в Событие. Думая об этом еще немного, я не могу решить, есть ли какие-либо концептуальные преимущества от получения свежей ценности от ofPoll по сравнению с получением ее из внешнего источника или наоборот. С другой стороны, я не совсем понимаю проблему блокировки пакета «до», пока не будет прочитано новое значение, и только затем активирует событие, которое фактически вызвало эту оценку (одновременно с событием изменений), но вы знаете свою библиотеку намного лучше меня – oggy

 Смежные вопросы

  • Нет связанных вопросов^_^