Lazy conclusion from monadic action

I have the following monad transformer:

newtype Pdf' m a = Pdf' {
  unPdf' :: StateT St (Iteratee ByteString m) a
  }
type Pdf m = ErrorT String (Pdf' m)

It mainly uses a basic Iterateeone that reads and processes a pdf document (a random access source is required so that it does not keep the document in memory all the time).

I need to implement a function that saves a PDF document, and I want it to be lazy, it should be possible to save the document in read-only memory.

I can create lazy ByteString:

import Data.ByteString.Lazy (ByteString)
import qualified Data.ByteString.Lazy as BS
save :: Monad m => Pdf m ByteString
save = do
  -- actually it is a loop
  str1 <- serializeTheFirstObject
  storeOffsetForTheFirstObject (BS.length str1)
  str2 <- serializeTheSecondObject
  storeOffsetForTheSecondObject (BS.length str2)
  ...
  strn <- serializeTheNthObject
  storeOffsetForTheNthObject (BS.length strn)
  table <- dumpRefTable
  return mconcat [str1, str2, ..., strn] `mappend` table

But the actual conclusion may depend on the previous conclusion. (Details: a pdf document contains a so-called “referenced table” with an absolute offset in bytes of each object within the document. This definitely depends on the length ByteStringof the pdf object that is serialized.)

, save ByteString, ?

, - ?

import Data.ByteString (ByteString)
save :: Monad m => (ByteString -> Pdf m ()) -> Pdf m ()

?

+5
2

, , Coroutine :

proc :: Int -> Coroutine (Yield String) IO ()
proc 0 = return ()
proc i = do
  suspend $ Yield "Hello World\n" (proc $ i - 1)

main :: IO ()
main = do
  go (proc 10)
  where
  go cr = do
    r <- resume cr
    case r of
      Right () -> return ()
      Left (Yield str cont) -> do
        putStr str
        go cont

, , .

0

, (, ), . , , . , Pdf- . , , , xref.

, .

6 : , . , . HTML, hackage "blaze" . , "mconcat" ByteString "". , , 'blaze-builder', 'blaze-html' 'blaze-textual'.

0

All Articles