1

キーの押下をキャッチし、それに応じてコード バッファーを操作するとします。

let
    bCode = accumB emptyCode eModifications
eCodeChanges <- changes bCode

別の動作を作成したいbEval

bEval = accumB freshEnv (magic eCodeChanges)

コードの状態をその評価にマップします (何かが実際に変更された場合にのみトリガーされます)。

ただし、評価はモナドで行われInterpreterます (ハックから考えhintてください)。実際にそのような動作を定義できますbEvalか? Interpreter Stringで累積して、動作の状態としてドラッグすることもできると思いますが、実際にcurrentAccumState >>= eval nextEventどこでrunInterpreter評価を強制するのでしょうか?


編集:重要なことは、アクションは単に状態を変更するだけではなくIO ()、何らかの状態を変更することになっているということです。たとえば、バッファのクリア/カウンターのリセット/ジッパーの周りの移動を検討してください。

私の考えは次のようなものでした:

f :: a -> Maybe (b -> IO b)

mapJustIO :: (a -> Maybe (b -> IO b)) -> Event t a -> Event t (b -> IO b)
mapJustIO f e = filterJust $ f <$> e

accumIO :: a -> Event t (a -> IO a) -> Behaviour t (IO a)
accumIO z e = fold (>>=) (return z) e

なぜこのようなことができなかったのかわかりません。ただし、動作でそれを取り除く方法もわかりませんIO:)。

IOオカレンスがreactive-banana実際にのみではないのはなぜMonadIOですか?

4

1 に答える 1

1

簡単に言えば、コンビネータのようなものは純粋なaccumB関数でしか機能しないということです。アクションの順序を意味のある方法で定義する方法がないため、それらは IO モナド (または のような別の IO に似たモナド) の関数を扱うことができません。Interpreter

IO アクションを操作するには、 のコンビネータReactive.Banana.Frameworksが適切です。たとえば、おそらく次のような関数が必要です

mapIO' :: (a -> IO b) -> Event a -> MomentIO (Event b)

詳細については、以前の回答を参照してください。

Interpreterのモナドの場合hint、メイン スレッドで実行し、FRP ロジック用に別のスレッドをフォークし、2 つの間の通信にTVars またはを使用することをお勧めします。TChan(私はこれをフォークリフト パターンと呼んでいます)。Interpreterこのようにして、からモナドにアクセスできますIO

于 2015-10-13T09:37:11.400 に答える