Estoy tratando de encontrar el equivalente de "wc -l" usando la biblioteca Haskell Iteratee. A continuación se muestra el código para "WC" (que simplemente cuenta las palabras - similar al código de ejemplo iteratee en hackage), y corre muy rápido:Escribiendo "wc -l" usando la biblioteca Iteratee - ¿cómo filtrar por nueva línea?
{-# 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
-}
Ahora, ¿cómo lo extiendes para contar el número de líneas que también corre rápido? Hice una versión usando Prelude.filter para filtrar solo "\ n" a la longitud, pero es más lento que Linux "wc -l" debido a demasiada memoria, y gc (evaluación lenta, supongo). Por lo tanto, escribí otra versión utilizando Data.ListLike.filter pero no va a compilar ya que no escribe cheque - ayudar aquí sería apreciada:
{-# 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
Gracias, Juan. Comentarios muy útiles. Mi propósito aquí fue comprender cómo escribirlos usando bloques básicos para que pudiera entender iteratee. Sus comentarios ayudan con la forma de escribir el código que está más allá del código de juguete. – Sal