以随机的ByteString为例,有效地生成了惰性ByteString

时间:2018-07-17 06:37:15

标签: haskell recursion lazy-evaluation bytestring

通过递归有效生成延迟ByteString似乎有一些障碍。为了证明这一点,选择的任务是制作一个惰性随机ByteString。 (随机数生成只是一个有意义的操作,即占位符,可能会引起任何其他递归。)

这是创建固定长度ByteString的随机惰性n的两次尝试。他们分配了大量的堆。首先是一些进口:

import qualified Data.ByteString.Lazy as BSL
import Data.Word8
import System.Random

现在使用cons的函数:

lazyRandomByteString1 :: Int -> StdGen -> BSL.ByteString
lazyRandomByteString1 n g = fst3 $ iter (BSL.empty, n, g) where
    fst3 (a, _, _) = a
    iter (bs', n', g') =
        if n' == 0 then (bs', 0, g')
        else iter (w `BSL.cons` bs', n'-1, g'') where
            (w, g'') = random g' :: (Word8, StdGen)

同样,只是使用unfoldr较短,但几乎和上面一样糟糕:

lazyRandomByteString2 :: Int -> StdGen -> BSL.ByteString
lazyRandomByteString2 n g = BSL.unfoldr f (n, g) where
    f :: (Int, StdGen) -> (Int, StdGen)
    f (n', g') =
        if n' == 0 then Nothing
        else Just (w, (n'-1, g'')) where
            (w, g'') = random g' :: (Word8, StdGen)

Data.ByteString.Lazy提供的内容中,所有这些都是通过递归创建ByteStrings的可用选项。

接下来,转到Data.ByteString.Lazy.Builder,它是为构建惰性ByteStrings而构建的,肯定会提高效率:

import Data.ByteString.Lazy.Builder (Builder, toLazyByteString, word8)

lazyRandomByteString3 :: Int -> StdGen -> BSL.ByteString
lazyRandomByteString3 n g = toLazyByteString builder where
    builder :: Builder
    builder = fst3 $ iter (mempty, n, g) where
        fst3 (a, _, _) = a
        iter :: (Builder, Int, StdGen) -> (Builder, Int, StdGen)
        iter (b, n', g') =
            if n' == 0 then (b, 0, g')
            else iter (b <> (word8 w), n'-1, g'') where
                (w, g'') = random g' :: (Word8, StdGen)

但不是。

Builder确实应该能够有效地做到这一点,不是吗? lazyRandomByteString3有什么问题?

源代码位于github上。

0 个答案:

没有答案