hGetContents
no es demasiado flojo, solo tiene que ser compuesto con otras cosas de manera apropiada para obtener el efecto deseado. Tal vez la situación sería más clara si se renombrara como exposeContentsToEvaluationAsNeededForTheRestOfTheAction
o simplemente listen
.
withFile
abre el archivo, hace algo (o nada, como usted por favor - exactamente lo que usted requiere de él, en cualquier caso), y cierra el archivo.
Difícilmente será suficiente para llevar a cabo todos los misterios de 'IO perezoso', pero ahora considerar esta diferencia de horquillado
good file operation = withFile file ReadMode (hGetContents >=> operation >=> print)
bad file operation = (withFile file ReadMode hGetContents) >>= operation >>= print
-- *Main> good "lazyio.hs" (return . length)
-- 503
-- *Main> bad "lazyio.hs" (return . length)
-- 0
crudamente, bad
abre y cierra el archivo antes de hacer nada; good
hace todo lo posible entre abrir y cerrar el archivo. Su primera acción fue similar a bad
.withFile
debe gobernar toda la acción que desee que dependa del asa.
No necesita un rigor enforcer si está trabajando con String
, archivos pequeños, etc., solo una idea de cómo funciona la composición. De nuevo, en bad
todo lo que 'hago' antes de cerrar el archivo es exposeContentsToEvaluationAsNeededForTheRestOfTheAction
. En good
compongo exposeContentsToEvaluationAsNeededForTheRestOfTheAction
con el resto de la acción que tengo en mente, luego cierro el archivo.
El familiarizado length
+ seq
truco mencionado por Patrick, o length
+ evaluate
vale la pena conocer; su segunda acción con putStrLn txt
fue una variante. Pero la reorganización es mejor, a menos que la pereza IO sea incorrecta para su caso.
$ time ./bad
bad: Prelude.last: empty list
-- no, lots of Chars there
real 0m0.087s
$ time ./good
'\n' -- right
()
real 0m15.977s
$ time ./seqing
Killed -- hopeless, attempting to represent the file contents
real 1m54.065s -- in memory as a linked list, before finding out the last char
No hace falta decir que ByteString y texto son vale la pena conocer, pero la reorganización con la evaluación en cuenta es mejor, ya que incluso con ellos las variantes perezosos son a menudo lo que necesita, y que luego implican agarrar las mismas distinciones entre formas de composición. Si está tratando con una de las (inmensa) clases de casos en los que este tipo de IO es inapropiado, eche un vistazo a enumerator
, conduit
y co., Todo maravilloso.
¿Podría mostrar el código donde usa 'hClose' usted mismo? Parece que lo estás cerrando antes de que se requiera la entrada. –