ByteStringsourceFile
ストリームを取得します。
私の他の質問「複数のソース/プロデューサーを1つに結合する」をZipSink
参照すると、を使用して(StdGen、ByteString)のsourceFile
ソースと、StdGenの無限ストリームを生成するカスタムソースを取得できます。
私が達成しようとしているのは、各 StdGen を 1 バイトの ByteString とペアにすることですが、現在の実装では、入力ファイルの内容全体とペアになった 1 つの StdGen を取得していますsourceFile
。
Conduit.Binary
の関数を調べましisolate
たが、次のように使用するとうまくいかないようです。
{-# 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
import Data.Conduit.Binary (isolate)
-- 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 $= isolate 1)
-- 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"
Conduit の用語では、受信 ByteString ストリームの を生成しisolate
、残りを (受信ストリームのキューに戻す) と考えました。基本的に、私がやろうとしているのは、着信 ByteString ストリームをバイトのブロックに切り刻むことです。await
head
leftOver
私はそれを正しく使用していますか?私が使用すべき関数ではない場合isolate
、誰かがそれを任意のバイトチャンクに分割する別の関数を提供できますか?