21

I've used zipSinks :: Monad m => Sink i m r -> Sink i m r' -> Sink i m (r, r') for this but it is considered deprecated.

4

2 回答 2

7

编辑

考虑到这一点,我认为当前版本的 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返回NothingmaybeToList则返回一个空列表,因此子接收器也会在没有输入的情况下运行。最后,然后将每个子接收器的输出馈送到元组中。

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和外部都可以正常工作,并且在我所做的少数测试中,输出与zipped'使用旧的zipSinks.

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)
于 2012-08-15T19:14:55.190 回答
6

(((包是conduit-0.5.2.3。整个模块只是为了向后兼容。))


[编辑]

所以,我直截了当的一元猜测(见下文)似乎是错误的,即使类型是正确的。现在,我只能猜测答案是:

替换功能仍在开发中,与所有 Pipe/Conduit 以及类似的概念和库非常相似。

我会等待下一个 API 来解决这个问题并在此zipSink之前仍然使用。(也许只是放错地方了。)

[ /编辑]

我对这个包不是很熟悉,但它不会和这个一样吗?

zipSinks :: Monad m => Sink i m r -> Sink i m r' -> Sink i m (r, r')
zipSinks s1 s2 = (,) <$> s1 <*> s2

毕竟这是一个Monad 。(函子,应用)

zipSinks :: Monad sink => sink r -> sink r' -> sink (r, r')
zipSinks s1 s2 = liftM2 (,) s1 s2
于 2012-08-14T16:42:36.167 回答