我使用sourceFile
从文件中读取,但我还需要在处理操作中引入随机性。我认为最好的方法是拥有一个
Producer m (StdGen, ByteString)
其中StdGen用于生成随机数。
我打算让生产者执行sourceFile的任务,并在每次向下游发送数据时生成一个新的种子。
我的问题是,对于接收器来说,似乎不是像zipSink
这样的源组合器。阅读Conduit Overview,似乎暗示您可以在Source
内嵌入Conduit
,但我未能在示例中看到它是如何完成的。
任何人都可以提供一个示例,将两个或多个IO资源合并为一个Producer
/ Source
吗?
编辑:
一个例子:
{-# 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"
因此,此示例获取输入文件中的内容并将其写入输出文件,并将40到50之间的随机ASCII值附加到文件末尾。 (不要问我为什么)
答案 0 :(得分:5)
您可以使用ZipSource。在您的情况下,它可能看起来像:
sourceStdGens :: Source m StdGen
sourceBytes :: Source m ByteString
sourceBoth :: Source m (StdGen, ByteString)
sourceBoth = getZipSource $ (,)
<$> ZipSource sourceStdGens
<*> ZipSource sourceBytes
答案 1 :(得分:2)
您可以在IO monad中执行此操作,然后将结果提升到Producer。
do (i, newSeed) <- next currentSeed
b <- generateByteStringFromRandomNumber i
return (b, newSeed)
可以通过简单的提升将IO动作提升到适当的管道中:
-- assuming the above action is named x and takes the current seed as an argument
-- the corresponding producer/source is:
lift $ x currentSeed