Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何将多个管道合并为一个管道或将多个管道合并为一个管道_Haskell_Conduit - Fatal编程技术网

Haskell 如何将多个管道合并为一个管道或将多个管道合并为一个管道

Haskell 如何将多个管道合并为一个管道或将多个管道合并为一个管道,haskell,conduit,Haskell,Conduit,是否可以将多个管道合并为一个管道,或将多个管道合并为一个管道 我正在努力实现以下功能 merge :: (Monad m) => [Pipe l i o u m r] -> Pipe [l] [i] [o] m [r] split :: (Monad m) => Pipe [l] [i] [o] m [r] -> [Pipe l i o u m r] 正如其他人所评论的,合并管道具有多种语义 我知道在管道核心(Paolo Capriotti的fork of Gabri

是否可以将多个管道合并为一个管道,或将多个管道合并为一个管道

我正在努力实现以下功能

merge :: (Monad m) => [Pipe l i o u m r] -> Pipe [l] [i] [o] m [r]

split :: (Monad m) => Pipe [l] [i] [o] m [r] -> [Pipe l i o u m r]

正如其他人所评论的,合并管道具有多种语义

我知道在
管道核心
(Paolo Capriotti的fork of Gabriel Gonzalez的
管道
库,这是另一个迭代实现,如
管道
)中,有一些非常通用的单倍体和乘法类代码

例如,使用
PipeC
,这是一种新类型,它移动类型变量以使
PipeC m r
成为有效类别,我们可以将独立信号集多路复用为
s

还有类似于
sequence
的内容,它适用于
Monad
实例

sequence :: [m a] -> m [a]
这将“垂直”排列各种管道(一条接着一条),让我们编写类似这样的东西(使用冈萨雷斯的
管道
包中的
Control.Pipe.Pipe



您请求的类型同时暗示了这两种“合并”。这(我认为)是不可能的,因为你想要同时进行并行(多路复用)和顺序(垂直)合成。

从你的评论中,听起来你可以通过将一些接收器链接在一起更容易地完成你想要做的事情:

import Data.Conduit
import Data.Serialize.Put (putListOf, putWord32le)
import qualified Data.Conduit.Binary as Cb
import qualified Data.Conduit.List as Cl
import qualified Data.Conduit.Cereal as Cc

main :: IO ()
main = do
  let source = Cl.sourceList [[1,2,3],[4,5,6],[7,8,9]]
      encoder = Cc.conduitPut $ putListOf putWord32le

  runResourceT . runPipe $ source >+> do
    Cl.isolate 1 >+> encoder >+> Cb.sinkFile "/tmp/1.bin"
    Cl.isolate 1 >+> encoder >+> Cb.sinkFile "/tmp/2.bin"
    Cl.isolate 1 >+> encoder >+> Cb.sinkFile "/tmp/3.bin"
    Cl.sinkNull

你能概述一下你需要的行为吗?可以为源(连接或排序)和接收器(第一个接收器完成或全部完成时停止)构建相当通用的合并函数。管道合并趋向于更专业化。我不认为在没有IO的情况下拆分列表管道是可能的。@comatose我认为类型签名需要修复。
u
可能需要删除。@NathanHowell我想他想把一个管道列表合并成一个管道,这样他就可以输入一个列表了。合并[mapD(*2),mapD(+2)],将(*2)列表的第一个元素,并(+2)合并到第二个元素,如果列表较长,则合并失败,或者使用id。@Davorak有许多可能的方法来合并管道。以下是我常用的两种不同方法:
mergeSinks::(Monad m,monoidr)=>[Pipe I Void()m r]->Pipe I Void()m r
mergeSources::(Ord o,Monoid u,Monad m)=>[Pipe l I o u m()]->Pipe l I o u m()
。但他也可能想要
mconcat::[pipelioom()]->pipelioom()
。。。甚至是
foldM
,也很难猜测。@Davorak我错过了
[u]
,介于
[o]
m
之间。对于第二条评论,这正是我的意思。谢谢。嗯,我刚意识到你可能真的需要一个接收器路由器。我们使用两个,一个是同步的:
routeToSinksBy::(Monad m,Ord a)=>(i->a)->映射a(Sink i m r)->Sink i m(Map a r)
。。。如果有帮助的话,我可以把它清理并出版。另一个是异步的,使用从
TBQueue
s构建的源绑定到每个接收器。谢谢您的回答。但是,实际上,我想把
[1,4,7]
放到1.bin,
[2,5,8]
放到2.bin,
[3,6,9]
放到3.bin。如果有类似“转置”的东西,它会有帮助。还有,如果我有
循环[[1,2,3],[4,5,6],[7,8,9]
routeToSinkBy
听起来不错。我很期待。如果您参与了
导管
,我对
导管
有一个建议。最近,我找不到类似
sourceFile::monadersource m=>Int->FilePath->GSource m ByteString
,它有一个额外的参数用于
hGetSome
的数据包大小。我认为这在某些情况下会有所帮助。谢谢。我以前考虑过使用管道,但我没有考虑,因为没有通过限制
管道。不管怎样,谢谢你的回答。我只是举个例子。这些概念可能是任何受iteratee启发的库的通用概念。我非常喜欢
pipes
,尽管它在库支持方面肯定远远落后。
import Data.Conduit
import Data.Serialize.Put (putListOf, putWord32le)
import qualified Data.Conduit.Binary as Cb
import qualified Data.Conduit.List as Cl
import qualified Data.Conduit.Cereal as Cc

main :: IO ()
main = do
  let source = Cl.sourceList [[1,2,3],[4,5,6],[7,8,9]]
      encoder = Cc.conduitPut $ putListOf putWord32le

  runResourceT . runPipe $ source >+> do
    Cl.isolate 1 >+> encoder >+> Cb.sinkFile "/tmp/1.bin"
    Cl.isolate 1 >+> encoder >+> Cb.sinkFile "/tmp/2.bin"
    Cl.isolate 1 >+> encoder >+> Cb.sinkFile "/tmp/3.bin"
    Cl.sinkNull