Haskell enumerator: analog of iteration of the enumWith` operator?

Earlier today, I wrote a small test application for iterations that compiled an iteration to record progress using iteration to actually copy data. I got the following values:

-- NOTE: this snippet is with iteratees-0.8.5.0 -- side effect: display progress on stdout displayProgress :: Iteratee ByteString IO () -- side effect: copy the bytestrings of Iteratee to Handle fileSink :: Handle -> Iteratee ByteString IO () writeAndDisplayProgress :: Handle -> Iteratee ByteString IO () writeAndDisplayProgress handle = sequence_ [fileSink handle, displayProgress] 

When viewing the library of counters, I do not see an analogue of sequence_ or enumWith . All I want to do is make two iterations so that they act as one. I could discard the result (it will be () anyway) or save it, I don't care. (& & &) from Control.Arrow is what I want, only for iterations, not arrows.

I tried these two options:

 -- NOTE: this snippet is with enumerator-0.4.10 run_ $ enumFile source $$ sequence_ [iterHandle handle, displayProgress] run_ $ enumFile source $$ sequence_ [displayProgress, iterHandle handle] 

The first copies the file, but does not show progress; the second shows the progress, but does not copy the file, so it is obvious that the effect of the built-in sequence_ on the repeater will list to start the first iteratee until it completes, and then run another, which I don't want. I want to run iterations in parallel, and not alternately. I feel like I'm missing something obvious, but as I read the wc example for an enumerator library, I see this curious comment:

 -- Exactly matching wc output is too annoying, so this example -- will just print one line per file, and support counting at most -- one statistic per run 

I wonder if this remark indicates that combining or drawing up iterations within the enumerations is not possible out of the box. What is the generally accepted right way to do this?

Edit

There seems to be no built-in way to do this. It discusses the Haskell mailing list about adding combinators like enumSequence and manyToOne , but so far there seems to be nothing in the enumerator package that provides this feature.

+6
source share
1 answer

It seems to me that instead of trying to use two Iteratees sequences in parallel, it would be better to pass the stream through the Enumeratee identifier, which simply counts the bytes that transmit it.

Here is a simple example that copies a file and prints the number of bytes copied after each fragment.

 import System.Environment import System.IO import Data.Enumerator import Data.Enumerator.Binary (enumFile, iterHandle) import Data.Enumerator.List (mapAccumM) import qualified Data.ByteString as B printBytes :: Enumeratee B.ByteString B.ByteString IO () printBytes = flip mapAccumM 0 $ \total bytes -> do let total' = total + B.length bytes print total' return (total', bytes) copyFile st = withBinaryFile t WriteMode $ \h -> do run_ $ (enumFile s $= printBytes) $$ iterHandle h main = do [source, target] <- getArgs copyFile source target 
+2
source

Source: https://habr.com/ru/post/892729/


All Articles