Note that there are some explanatory texts on larger screens.

plurals
  1. POWriting "wc -l" using Iteratee library - how to filter for newline?
    text
    copied!<p>I am trying to come up with equivalent of "wc -l" using Haskell Iteratee library. Below is the code for "wc" (which just counts the words - similar to the code in iteratee example on hackage), and runs very fast:</p> <hr> <pre class="lang-hs prettyprint-override"><code>{-# LANGUAGE BangPatterns #-} import Data.Iteratee as I import Data.ListLike as LL import Data.Iteratee.IO import Data.ByteString length1 :: (Monad m, Num a, LL.ListLike s el) =&gt; Iteratee s m a length1 = liftI (step 0) where step !i (Chunk xs) = liftI (step $ i + fromIntegral (LL.length xs)) step !i stream = idone i stream {-# INLINE length1 #-} main = do i' &lt;- enumFile 1024 "/usr/share/dict/words" (length1 :: (Monad m) =&gt; Iteratee ByteString m Int) result &lt;- run i' print result {- Time measured on a linux x86 box: $ time ./test ## above haskell compiled code 4950996 real 0m0.013s user 0m0.004s sys 0m0.007s $ time wc -c /usr/share/dict/words 4950996 /usr/share/dict/words real 0m0.003s user 0m0.000s sys 0m0.002s -} </code></pre> <hr> <p>Now, how do you extend it to count the number of lines that too runs fast? I did a version using Prelude.filter to filter only "\n" to length but it is slower than linux "wc -l" because of too much memory, and gc (lazy evaluation, I guess). So, I wrote another version using Data.ListLike.filter but it won't compile because it doesn't type check - help here would be appreciated:</p> <hr> <pre class="lang-hs prettyprint-override"><code> {-# LANGUAGE BangPatterns #-} import Data.Iteratee as I import Data.ListLike as LL import Data.Iteratee.IO import Data.ByteString import Data.Char import Data.ByteString.Char8 (pack) numlines :: (Monad m, Num a, LL.ListLike s el) =&gt; Iteratee s m a numlines = liftI $ step 0 where step !i (Chunk xs) = liftI (step $i + fromIntegral (LL.length $ LL.filter (\x -&gt; x == Data.ByteString.Char8.pack "\n") xs)) step !i stream = idone i stream {-# INLINE numlines #-} main = do i' &lt;- enumFile 1024 "/usr/share/dict/words" (numlines :: (Monad m) =&gt; Iteratee ByteString m Int) result &lt;- run i' print result </code></pre>
 

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