7

Haskell でリアクティブ バナナを使用して音楽プレーヤーを作成しています。私が抱えている問題の 1 つは、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は部分的な関数であり、再生が実際に開始される前にNothingを返します。問題は、addCmdEventが初めて発生すると、bPositionがまだNothing値を保持していることです。eSetStart/Endは、これに基づいて値を計算します。そうして初めてbPositionが更新され、これが次回の addCmdEvent の起動時に使用される値になります。など、いわば値は常に「1つずれている」ことになります。

関連するSO questionがありますが、その場合、動作の新しい値を計算するために使用できる「トリガー」イベントが存在します。fromPollでそのようなことは可能ですか?

4

1 に答える 1

2

Reactive-banana-0.5 および 0.6 の時点で、fromPoll関数は、外部イベントがイベント ネットワークをトリガーするたびに動作を更新します。を使用して、これらの更新にイベントとしてアクセスできます。

eUpdate <- changes bSomeBehavior

ただし、ビヘイビアーは、「更新イベント」の一般的な概念をサポートしていない連続的な時変値を表すことに注意してください。このchanges関数は有用な近似値を返そうとしますが、正式な保証はありません。

または、外部イベントを変更して、プレーヤーの位置を の一部として含めることもできますaddCmdEventSetStartあなたの場合、これはコンストラクタとコンストラクタにデータを追加することを意味しますSetEnd。次に、使用できます

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

どちらのソリューションでも、最新の値を動作ではなくイベントとして観察する必要があります。その理由は、 で作成されたビヘイビアは、stepper更新された時点で常に古い値を返す (「1 遅れる」) ためです。これは、再帰的な定義に非常に役立つからです。

いずれにせよ、根本的な問題は、プレーヤーの位置がaddCmdEvent発生するずっと前に外部で更新されることですが、問題は、これがイベント ネットワークで認識されるものではないことです。むしろ、ネットワークは、によって返された動作が と同時にfromPoll更新されると考えていますaddCmdEvent。実際、プレーヤーの位置の更新を担当する外部イベント ソースにアクセスできない限り、それが考えられる唯一のことです。(アクセス権がある場合は、fromChanges機能を使用できます。)

のこの動作はfromPoll、一般的なユース ケースではやや不十分であることを認識しています。fromPollただし、ライブラリで修正する必要があるかどうかは未定です。最新の値を返すことと、changes関数が最善を尽くそうとすることの間にはトレードオフがあります。最新の値が返さchangesれた場合、 は 1 つの更新をスキップしたかのように動作し (値が外部で更新された場合)、余分な更新をトリガーしました (ネットワークが外部の値と一致するように値を更新した場合)。これについてご意見がありましたら、お知らせください。


ビヘイビアーを applicative オペレーター<*>と組み合わせると、最新の値が適切に結合されることに注意してください。

于 2012-05-29T12:16:37.870 に答える