Я читаю из файла с помощью sourceFile
, но мне также нужно ввести случайность в операцию обработки. Я считаю, что лучший подход — это иметь продюсера типа
Producer m (StdGen, ByteString)
где StdGen используется для генерации случайного числа.
Я намереваюсь, чтобы производитель выполнял задачу исходного файла, а также создавал новое семя для получения урожая каждый раз, когда он отправляет данные вниз по течению.
Моя проблема в том, что, похоже, нет такого объединителя источников, как zipSink
для приемников. Чтение обзора канала кажется, что вы можете встроить Source
внутрь Conduit
, но я не вижу, как это делается в примере.
Может ли кто-нибудь привести пример, в котором вы объединяете два или более источника ввода-вывода в один единственный 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"
Таким образом, этот пример берет то, что находится во входном файле, и записывает его в выходной файл, а также добавляет случайное значение ASCII между 40 и 50 в конец файла. (Не спрашивайте меня, почему)