簡體   English   中英

Iteratees和FRP之間有什么聯系?

[英]What is the connection between Iteratees and FRP?

在我看來,這兩個想法之間存在着密切的聯系。 我的猜測是,如果有一種方法可以用迭代器表示任意圖形,那么FRP可以用Iteratees來實現。 但是afaik他們只支持鏈式結構。

有人可以對此有所了解嗎?

這是相反的方式。 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是一系列應用函子,所以要將一個簡單的函數應用於流元素,你可以使用fmap

fmap (B.map toUpper) . readFile

為了您的方便,它也是一個系列的教師。

最有趣的功能是這是一系列替代函子。 這允許您路由流並允許多個流處理器在放棄之前“嘗試”。 這可以擴展到一個完整的解析庫,甚至可以使用一些靜態信息進行優化。

您可以使用流處理器實現有限形式的FRP。 例如,使用pipes庫,您可以定義事件源:

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

...您可以類似地定義一個圖形處理程序,它接受鼠標坐標並更新畫布上的光標:

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

然后,您將使用組合將鼠標事件連接到處理程序:

>>> runProxy $ mouseCoordinates >-> coordHandler

它會像你期望的那樣運行。

就像你說的那樣,這適用於單個連鎖階段,但是更多的任意拓撲呢? 好吧,事實證明,由於中央Proxy類型的pipes是monad變換器,你可以通過在它們自己之上嵌套代理monad變換器來建模任何任意拓撲。 例如,以下是如何壓縮兩個輸入流:

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

這表現得像一個curried函數。 您可以按順序將其部分應用於每個輸入,然后可以在完全應用它時運行它。

-- 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中找到有關此內容的更多詳細信息。 特別是,您應該檢查它使用的fork組合器作為示例,它允許您將流拆分為兩個輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM