我已经习惯zipSinks :: Monad m => Sink i m r -> Sink i m r' -> Sink i m (r, r')
了这个,但它被认为已被弃用了.
编辑
考虑到这一点后,我不认为使用当前版本的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)
Run Code Online (Sandbox Code Playgroud)
现在为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)
Run Code Online (Sandbox Code Playgroud)
以下是一些使用示例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)
Run Code Online (Sandbox Code Playgroud)
((包是conduit-0.5.2.3.整个模块只是为了向后兼容.))
[ 编辑 ]
所以,即使类型是正确的,我直截了当的monadic猜测(见下文)似乎是错误的.现在,我只能猜到答案是:
替换功能仍在开发中,非常类似于所有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
Run Code Online (Sandbox Code Playgroud)
毕竟这是Monad.(Functor,Applicative)
zipSinks :: Monad sink => sink r -> sink r' -> sink (r, r')
zipSinks s1 s2 = liftM2 (,) s1 s2
Run Code Online (Sandbox Code Playgroud)