Haskell 导管-将多个源/生产商合并为一个

Haskell 导管-将多个源/生产商合并为一个,haskell,conduit,Haskell,Conduit,我正在使用sourceFile读取文件,但我还需要在处理操作中引入随机性。我认为最好的办法是有一个这样的制作人 Producer m (StdGen, ByteString) 其中StdGen用于生成随机数 我打算让生产者执行sourceFile的任务,并在每次向下游发送数据时生成一个新种子 我的问题是,对于接收器,似乎没有像zipSink那样的源组合器。通读一遍,它似乎建议您可以将源代码嵌入到管道中,但我没有看到在示例中是如何实现的 任何人都可以提供一个示例,说明如何将两个或多个IO源融合到

我正在使用
sourceFile
读取文件,但我还需要在处理操作中引入随机性。我认为最好的办法是有一个这样的制作人

Producer m (StdGen, ByteString)
其中StdGen用于生成随机数

我打算让生产者执行sourceFile的任务,并在每次向下游发送数据时生成一个新种子

我的问题是,对于接收器,似乎没有像
zipSink
那样的源组合器。通读一遍,它似乎建议您可以将
源代码
嵌入到
管道
中,但我没有看到在示例中是如何实现的

任何人都可以提供一个示例,说明如何将两个或多个IO源融合到一个
生产者
/

编辑:

例如:

{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE OverloadedStrings #-}

import System.Random (StdGen(..), split, newStdGen, randomR)
import ClassyPrelude.Conduit as Prelude
import Control.Monad.Trans.Resource (runResourceT, ResourceT(..))
import qualified Data.ByteString as BS

-- generate a infinite source of random number seeds
sourceStdGen :: MonadIO m => Source m StdGen
sourceStdGen = do
    g <- liftIO newStdGen
    loop g
    where loop gin = do
            let g' = fst (split gin)
            yield gin
            loop g'

-- combine the sources into one
sourceInput :: (MonadResource m, MonadIO m) => FilePath -> Source m (StdGen, ByteString)
sourceInput fp = getZipSource $ (,)
    <$> ZipSource sourceStdGen
    <*> ZipSource (sourceFile fp)

-- a simple conduit, which generates a random number from provide StdGen
-- and append the byte value to the provided ByteString
simpleConduit :: Conduit (StdGen, ByteString) (ResourceT IO) ByteString
simpleConduit = mapC process 

process :: (StdGen, ByteString) -> ByteString
process (g, bs) =
    let rnd = fst $ randomR (40,50) g
    in bs ++ pack [rnd]

main :: IO ()
main = do
    runResourceT $ sourceInput "test.txt" $$ simpleConduit =$ sinkFile "output.txt"
{-#语言无mplicitprelude}
{-#语言等级}
{-#语言重载字符串}
导入系统.Random(StdGen(..)、split、newStdGen、randomR)
导入ClassyPrelude。导管作为前奏
导入控制.Monad.Trans.Resource(runResourceT,ResourceT(..)
将符合条件的数据.ByteString作为BS导入
--生成无限个随机数种子源
sourceStdGen::MonadIO m=>Source m StdGen
sourceStdGen=do
g文件路径->源m(StdGen,ByteString)
sourceInput fp=getZipSource$(,)
ZipSourceStdGen
ZipSource(源文件fp)
--一个简单的导管,它从提供的StdGen生成一个随机数
--并将字节值附加到提供的ByteString
simplencuduit::导管(StdGen,ByteString)(ResourceT IO)ByteString
simplencuduit=mapC进程
进程::(StdGen,ByteString)->ByteString
工艺(g、bs)=
设rnd=fst$randomR(40,50)g
在bs++包中[rnd]
main::IO()
main=do
runResourceT$sourceInput“test.txt”$$simplencuduit=$sinkFile“output.txt”

因此,本例获取输入文件中的内容并将其写入输出文件,同时在文件末尾附加一个40到50之间的随机ASCII值。(不要问我为什么)

你可以在IO单子中完成,然后将结果提交给制作人

do (i, newSeed) <- next currentSeed
   b <- generateByteStringFromRandomNumber i
   return (b, newSeed)
你可以用这个。在您的情况下,它可能看起来像:

sourceStdGens :: Source m StdGen
sourceBytes :: Source m ByteString
sourceBoth :: Source m (StdGen, ByteString)
sourceBoth = getZipSource $ (,)
    <$> ZipSource sourceStdGens
    <*> ZipSource sourceBytes
sourcestdgen::Source m StdGen
sourceBytes::Source m ByteString
sourceBoth::sourcem(StdGen,ByteString)
sourceBoth=getZipSource$(,)
ZipSource源代码
ZipSource源字节

或者,如果您只需要压缩两个源,
Data.conductor.Internal.zipSources
,但是
ZipSource
类型通过为输出参数添加一个
Applicative
实例来概括该函数。您能否提供一个示例,将IO操作“提升”到
生产者
?如果您想要管道中的随机性,请使用monad random。
sourceStdGens :: Source m StdGen
sourceBytes :: Source m ByteString
sourceBoth :: Source m (StdGen, ByteString)
sourceBoth = getZipSource $ (,)
    <$> ZipSource sourceStdGens
    <*> ZipSource sourceBytes