[Haskell-cafe] 'Progress bar' enumeratee

David Hotham david.hotham at blueyonder.co.uk
Wed Apr 6 21:21:37 CEST 2011

The desired behaviour (certainly my desired behaviour, but I think also the 
most useful behaviour generally) is that the enumeratee passes n bytes to 
its iteratee, prints a dot, and repeats.

Given that, printing the dots all in one bunch after passing bytes to the 
iteratee isn't any improvement over printing the dots all in one bunch 
before passing them to the iteratee.

I think that mostly I want it the way that I want it because that's the bit 
that I struggled most over and I'm now reluctant to give it up!  However 
this might actually make a useful difference to behaviour in the case of an 
iteratee that did very expensive processing, or that itself performed IO. 
In such cases, my behaviour could be expected to give a more accurate 
indication of how far through processing we'd actually got.


PS Yes, I already tried out the code ;-).  You'll see that both of my 
versions did indeed hFlush stdout.

"Ertugrul Soeylemez" <es at ertes.de> wrote in message 
news:20110406182931.0238561f at angst.streitmacht.eu...
> "David Hotham" <david.hotham at blueyonder.co.uk> wrote:
>> I did have a version along those lines at some point, but I felt it
>> was cheating rather to print the dots not at the correct point in the
>> stream.
>> Perhaps I've over-complicated for the sake of the learning experience,
>> but I do like to have a version that passes on the correct number of
>> bytes, then prints the ".", and then continues.
> Well, then just do the printing after calling the continuation:
>    dotsAt :: forall b m. MonadPeelIO m => Int ->
>              Enumeratee ByteString ByteString m b
>    dotsAt n =
>        loop 0
>        where
>        loop :: Int -> Enumeratee ByteString ByteString m b
>        loop i' step@(Continue k) =
>            continue go
>            where
>            go :: Stream ByteString ->
>                  Iteratee ByteString m (Step ByteString m b)
>            go EOF = return step
>            go ch@(Chunks strs) = do
>                let (numDots, i) = divMod (i' + sum (L.map BC.length strs)) 
> n
>                    printDots = tryIO $ BC.putStr (BC.replicate numDots 
> '.') >>
>                                        hFlush stdout
>                k ch >>== (\step -> printDots >> loop i step)
>        loop i' step = return step
> By the way, after trying out the code, I found that you should use
> hFlush after printing.  Otherwise you may see the dots delayed.
> Greets,
> Ertugrul
> -- 
> nightmare = unsafePerformIO (getWrongWife >>= sex)
> http://ertes.de/ 

More information about the Haskell-Cafe mailing list