我已經使用zipSinks :: Monad m => Sink i m r -> Sink i m r' -> Sink i m (r, r')
這個,但它被認爲不推薦。組合兩個接收器的首選方法是什麼?
回答
((包是conduit-0.5.2.3,整個module只是爲了向下兼容。))
[編輯]
所以,我簡單的一元猜想(見下文)似乎是錯誤,即使類型是正確的。 現在,我只能猜測答案是:
替換功能仍在開發中,幾乎和所有Pipe/Conduit以及類似的概念和庫一樣。
我等待下一個API來解決這個問題,直到那時仍然使用zipSink
。 (也許這只是放錯了地方。)
[/編輯]
我不是這個包familar,但不會是做一樣的,因爲這?
zipSinks :: Monad m => Sink i m r -> Sink i m r' -> Sink i m (r, r')
zipSinks s1 s2 = (,) <$> s1 <*> s2
畢竟這是一個Monad。 (Functor,Applicative)
zipSinks :: Monad sink => sink r -> sink r' -> sink (r, r')
zipSinks s1 s2 = liftM2 (,) s1 s2
類型可以,但不是語義。您的zipSinks版本將連續運行接收器,並且第一個接收器將完全消耗源代碼。 – tymmym 2012-08-15 05:56:26
編輯
考慮在此之後,我不認爲這是可能的Data.Conduit的當前版本。管道不是類別,所以&&&
是不可能的。我不可能想到從上游獲得結果,逐步將它們提供給兩個接收器,並在第一個接收器結束時進行短路。 (雖然我不認爲Data.Conduit.Util.zipSinks
這樣短路,但它似乎是非常可取的。)除了當然,模式匹配在兩個水槽(如包中的zipSinks
),但這就是我們試圖避免在這裏。
這就是說,我會愛在這裏被證明是錯誤的。
這不是很漂亮,但你可以用一種明顯的方式做到這一點。
首先進口:
module Main where
import Control.Monad.Trans
import Data.Conduit
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.List as CL
import qualified Data.Conduit.Text as CT
import qualified Data.Conduit.Util as CU
import Data.Maybe
import Data.Text (unpack)
現在對於zipSinks
。基本上,您要創建一個接收器,從上游獲取輸入,並將其分別發送給每個子接收器。在這種情況下,我用CL.sourceList
來做到這一點。如果await
返回Nothing
,maybeToList
返回一個空列表,所以子接收器也在沒有輸入的情況下運行。最後,每個子宿的輸出被輸入到元組中。
zipSinks :: Monad m => Sink i m r -> Sink i m r' -> Sink i m (r, r')
zipSinks s1 s2 = do
l <- fmap maybeToList await
o1 <- lift $ CL.sourceList l $$ s1
o2 <- lift $ CL.sourceList l $$ s2
return (o1, o2)
以下是使用zipSinks
的一些示例。它似乎在IO
內部以及其外部均正常工作,並且在我進行的少數測試中,輸出與使用舊的zipSinks
創建的zipped'
的輸出相匹配。
doubleHead :: Monad m => Sink Int m (Maybe Int)
doubleHead = await >>= return . fmap (2*)
-- old version
zipped' :: Monad m => Sink Int m (Maybe Int, Maybe Int)
zipped' = CU.zipSinks CL.head doubleHead
-- new version
zipped :: Monad m => Sink Int m (Maybe Int, Maybe Int)
zipped = zipSinks CL.head doubleHead
fromList = CL.sourceList [7, 8, 9] $$ zipped
-- (Just 7, Just 14)
fromFile :: String -> IO (Maybe Int, Maybe Int)
fromFile filename = runResourceT $
CB.sourceFile filename
$= CB.lines
$= CT.decode CT.utf8
$= CL.map (read . unpack)
$$ zipped
-- for a file with the lines:
--
-- 1
-- 2
-- 3
--
-- returns (Just 1, Just 2)
不錯! (注意,你可以爲'doubleHead'寫'await >> = return。fmap(2 *)',同樣''l -fmap mayToList await'而不是在'zipSinks'中使用'input', Data.Conduit.Internals'是一個額外的導入?) – huon 2012-08-15 19:31:29
是的,我意識到我可能可以在某些地方使用函子。對於Haskell來說,我仍然足夠了,這對我來說通常是第二遍編輯,不幸的是。 是的,'Data.Conduits.Internals'是無關的。最初,我正在使用'sinkToPipe'。 感謝您指出這些。我會更新答案。 – Eric 2012-08-15 20:14:41
您的zipSinks版本只包含第一個元素。例如'runResourceT $ CL.sourceList [1,2,3] $$ zipSinks(CL.take 2)(CL.take 2)''會返回'([1],[1])',但應該是'([1 ,2],[1,2])'。 – tymmym 2012-08-16 05:49:07
- 1. 跨線程編組COM接口的首選方法是什麼?
- 2. 什麼是預先分配NumPy數組的首選方法?
- 3. 什麼是組織回調的首選方法?
- 4. 在貓鼬中定義數組的首選方法是什麼?
- 5. 數據更改時刷新組合框的首選方法是什麼?
- 6. 從Android上傳到服務器的首選方法是什麼?
- 7. 什麼是協調多個默認頁面的首選方法?
- 8. 在C#中處理這個TCP連接的首選方法是什麼?
- 9. 註釋中註釋方法的首選方式是什麼?
- 10. 從參數分配集合的首選方式是什麼?
- 11. 找到兩個集合的最有效方法是什麼?
- 12. 什麼是您的軟件版本的首選方法?
- 13. REST webservice的'WSDL'的首選方法是什麼?
- 14. 在VB.NET中聲明數組的首選語法是什麼?
- 15. 什麼是測試代理設置的首選或可接受的方法?
- 16. 跨瀏覽器協調keyCode/charCode的首選方式是什麼?
- 17. 無堆棧Python中TCP/IP IPC的首選方法是什麼?
- 18. 什麼是Zend Acl的首選實現方法
- 19. 在SSRS中生成數據集的首選方法是什麼?
- 20. 什麼是使用bash生成強密碼的首選方法?
- 21. C#中事件處理的首選方法是什麼?
- 22. 在.Net中構建Web服務的首選方法是什麼?
- 23. Zend 2中本地化的首選方法是什麼?
- 24. 在表格中更新字段的首選方法是什麼?
- 25. 什麼是OS X中進程間通信的首選方法?
- 26. Angular - 終止Observables的首選方法是什麼?
- 27. 現代D的首選控制檯輸出方法是什麼?
- 28. 處理缺少DynamicObject成員的首選方法是什麼?
- 29. 將視圖模型連接到視圖的首選方法是什麼?
- 30. 預加載圖像<img>的首選方法是什麼?爲什麼?
什麼樣的行爲,*確切*,你想要「合併」水槽有?我試着查看'zipSinks'的舊文檔和實現,但行爲不容易一眼就看出來。 – 2012-08-07 15:58:29
@DanBurton:'zipSinks'需要兩個接收器並返回一個接收器,該接收器會產生一個具有相應接收器結果的對。例如'sizeCrc32Sink = zipSinks sizeSink crc32Sink'會計算大小和校驗和。我和Oleg描述的行爲一樣[here](http://okmij.org/ftp/Streams.html#1enum2iter)。 – tymmym 2012-08-07 16:46:56
好吧,我明白了;它基本上掛起了等待並同時將上游輸出饋送到兩個接收器,將輸入流分成兩部分。 Data.Conduit.Util的文檔聲明「現在有更簡單的方法來處理它們的用例」,但我沒有看到這種用例的更簡單的方法,因爲它需要深入研究管道內部實現。 – 2012-08-08 03:46:05