19

二つの考えの間には強いつながりがあるように私には思えます。私の推測では、Iteratees で任意のグラフを表現する方法があれば、FRP は Iteratees の観点から実装できると思います。しかし、私の知る限り、彼らはチェーンのような構造しかサポートしていません。

誰かがこれに光を当てることができますか?

4

2 に答える 2

13

それは逆です。AFRP とストリーム処理の間には強いつながりがあります。実際、AFRPストリーム処理の形式であり、イディオムを使用して、パイプに非常に似たものを実装できます。

data Pipe m a b =
    Pipe {
      cleanup :: m (),
      feed    :: [a] -> m (Maybe [b], Pipe m a b)
    }

これは、Netwire に見られるワイヤ カテゴリの拡張です。入力の次のチャンクを受け取り、生成を停止すると Nothing を返します。これを使用すると、ファイル リーダーは次のタイプになります。

readFile :: (MonadIO m) => FilePath -> Pipe m a ByteString

Pipe は applicative functor のファミリーであるため、単純な関数をストリーム要素に適用するには、 fmapを使用するだけです:

fmap (B.map toUpper) . readFile

便宜上、profunctor のファミリーでもあります。

最も興味深い特徴は、これが代替ファンクターのファミリーであることです。これにより、ストリームをルーティングし、複数のストリーム プロセッサがあきらめる前に「試行」できるようになります。これは、最適化のためにいくつかの静的情報を使用することさえできる本格的な解析ライブラリに拡張できます。

于 2012-12-17T19:59:45.437 に答える
13

ストリーム プロセッサを使用して、限定された形式の FRP を実装できます。たとえば、pipesライブラリを使用して、イベントのソースを定義できます。

mouseCoordinates :: (Proxy p) => () -> Producer p MouseCoord IO r

... 同様に、マウス座標を取得してキャンバス上のカーソルを更新するグラフィカル ハンドラーを定義することもできます。

coordHandler :: (Proxy p) => () -> Consumer p MouseCoord IO r

次に、コンポジションを使用してマウス イベントをハンドラーに接続します。

>>> runProxy $ mouseCoordinates >-> coordHandler

そして、期待どおりに動作します。

あなたが言ったように、これはステージの単一チェーンではうまく機能しますが、より任意のトポロジーではどうでしょうか? の中心的なProxypipesはモナド変換子であるため、プロキシモナド変換子をそれらの上にネストするだけで、任意のトポロジをモデル化できることがわかります。たとえば、2 つの入力ストリームを圧縮する方法は次のとおりです。

zipD
 :: (Monad m, Proxy p1, Proxy p2, Proxy p3)
 => () -> Consumer p1 a (Consumer p2 b (Producer p3 (a, b) m)) r
zipD () = runIdentityP $ hoist (runIdentityP . hoist runIdentityP) $ forever $ do
    a <- request ()               -- Request from the outer Consumer
    b <- lift $ request ()        -- Request from the inner consumer
    lift $ lift $ respond (a, b)  -- Respond to the Producer

これは、カリー化された関数のように動作します。各入力に順次部分的に適用し、完全に適用されたときに実行できます。

-- 1st application
p1 = runProxyK $ zipD   <-< fromListS [1..]

-- 2nd application
p2 = runProxyK $ p2     <-< fromListS [4..6]

-- 3rd application
p3 = runProxy  $ printD <-< p3

期待どおりに実行されます。

>>> p3
(1, 4)
(2, 5)
(3, 6)

このトリックは、あらゆるトポロジーに一般化されます。これについての詳細は、Control.Proxy.Tutorialの「ブランチ、zip、およびマージ」セクションにあります。特に、forkストリームを 2 つの出力に分割できる例として使用するコンビネータを確認する必要があります。

于 2012-12-17T22:09:24.973 に答える