Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>For chunked input processing I would use the <a href="http://hackage.haskell.org/package/enumerator">enumerator</a> package.</p> <pre><code>import Data.Enumerator import Data.Enumerator.Binary (enumFile) </code></pre> <p>We use bytestrings</p> <pre><code>import Data.ByteString as BS </code></pre> <p>and IO</p> <pre><code>import Control.Monad.Trans (liftIO) import Control.Monad (mapM_) import System (getArgs) </code></pre> <p>Your main function could look like following:</p> <pre><code>main = do (filepath:_) &lt;- getArgs let destination run_ $ enumFile filepath $$ writeFile (filepath ++ ".cpy") </code></pre> <p>enumFile reads 4096 bytes per chunk and passes these to writeFile, which writes it down.</p> <p>enumWrite is defined as:</p> <pre><code>enumWrite :: FilePath -&gt; Iteratee BS.ByteString IO () enumWrite filepath = do liftIO (BS.writeFile filepath BS.empty) -- ensure the destination is empty continue step where step (Chunks xs) = do liftIO (mapM_ (BS.appendFile filepath) xs) continue step step EOF = yield () EOF </code></pre> <p>As you can see, the step function takes chunks of bytestrings and appends them to the destination file. These chunks have the type Stream BS.Bytestring, where Stream is defined as:</p> <pre><code>data Stream a = Chunks [a] | EOF </code></pre> <p>On an EOF step terminates, yielding ().</p> <p>To have a much more elaborate read on this I personally recommend Michael Snoymans <a href="http://www.yesodweb.com/book/enumerator">tutorial</a></p> <h2>The numbers</h2> <pre><code>$ time ./TestCopy 5MB ./TestCopy 5MB 2,91s user 0,32s system 96% cpu 3,356 total $ time ./TestCopy2 5MB ./TestCopy2 5MB 0,04s user 0,03s system 93% cpu 0,075 total </code></pre> <p>That's quite an improvement. Now in order to implement your fold you probably want to write an Enumeratee, which is used to transform a input stream. Fortunately there is already a map function defined in the enumerator package, which can be modified for your need, i.e. it can be modified to carry over state.</p> <h2>On the construction of the intermediate result</h2> <p>You construct wordsList in reverse order and reverse it afterwards. I think <a href="http://hackage.haskell.org/packages/archive/dlist/latest/doc/html/Data-DList.html">difference lists</a> do a better job, because appends take only O(1) time due to the fact that appending is only a function composition. I'm not sure whether they takes more space though. Here's a rough sketch of difference lists:</p> <pre><code>type DList a = [a] -&gt; [a] emptyList :: DList a emptyList = id snoc :: DList a -&gt; a -&gt; DList a snoc dlist a = dlist . (a:) toList :: DList a -&gt; [a] toList dlist = dlist [] </code></pre> <p>This answer is probably not needed anymore, but I added it for completeness.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload