Sto provando a inventare l'equivalente di "wc -l" usando la libreria Haskell Iteratee. Di seguito è riportato il codice per "wc" (che solo conta le parole - simile al codice dell'esempio iteratee su hackage), e corre molto veloce:Scrittura "wc -l" usando la libreria Iteratee - come filtrare per newline?
{-# 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) => 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' <- enumFile 1024 "/usr/share/dict/words" (length1 :: (Monad m) => Iteratee ByteString m Int)
result <- 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
-}
Ora, come si fa lo estendi per contare il numero di linee troppo veloci? Ho fatto una versione usando Prelude.filter per filtrare solo "\ n" in lunghezza ma è più lento di linux "wc -l" a causa della troppa memoria, e gc (valutazione pigra, immagino). Così, ho scritto un'altra versione utilizzando Data.ListLike.filter ma non compilerà perché non digita check - aiuto qui sarebbe apprezzato:
{-# 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) => Iteratee s m a
numlines = liftI $ step 0
where
step !i (Chunk xs) = liftI (step $i + fromIntegral (LL.length $ LL.filter (\x -> x == Data.ByteString.Char8.pack "\n") xs))
step !i stream = idone i stream
{-# INLINE numlines #-}
main = do
i' <- enumFile 1024 "/usr/share/dict/words" (numlines :: (Monad m) => Iteratee ByteString m Int)
result <- run i'
print result
Grazie, John. Feedback molto utile. Il mio scopo qui era capire come scriverli usando i blocchi elementari in modo che potessi capire l'iteratee. Il tuo feedback ti aiuta a scrivere il codice che va oltre il codice del giocattolo. – Sal