hGetContents
ist nicht zu faul, es muss nur mit anderen Dingen entsprechend zusammengesetzt werden, um den gewünschten Effekt zu erhalten. Vielleicht wäre die Situation klarer, wenn sie in exposeContentsToEvaluationAsNeededForTheRestOfTheAction
oder nur listen
umbenannt würde.
withFile
öffnet die Datei, tut etwas (oder nichts, wie Sie bitte - genau das, was Sie in jedem Fall benötigen), und schließt die Datei.
Es wird kaum ausreichen, alle Geheimnisse des ‚faulen IO‘ zu bringen, aber bedenken Sie jetzt diesen Unterschied in
Bracketing
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
Kunstlos setzen, bad
öffnet und schließt die Datei, bevor er etwas tut; good
macht alles zwischen dem Öffnen und Schließen der Datei. Ihre erste Aktion war verwandt mit bad
.withFile
sollte alle von Ihnen gewünschten Aktionen steuern, die vom Handle abhängen.
Sie brauchen keine Strenge Enforcer, wenn Sie mit String
, kleine Dateien usw. arbeiten, nur eine Idee, wie die Zusammensetzung funktioniert. Nochmals, in bad
alles, was ich vor dem Schließen der Datei "tun" ist exposeContentsToEvaluationAsNeededForTheRestOfTheAction
. In good
komponiere ich exposeContentsToEvaluationAsNeededForTheRestOfTheAction
mit dem Rest der Aktion, die ich im Sinn habe, dann schließe die Datei.
Der vertraute length
+ seq
Trick von Patrick erwähnt, oder length
+ evaluate
ist wert zu wissen; Ihre zweite Aktion mit putStrLn txt
war eine Variante. Aber Reorganisation ist besser, es sei denn, faule IO ist falsch für Ihren Fall.
$ 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
Es versteht sich, dass ByteString und Text wert sind: Jetzt wird gespart, aber Reorganisation mit Auswertung im Auge ist besser, da mit ihnen auch die faulen Varianten häufig sind, was Sie brauchen, und sie dann beinhalten die gleichen Unterschiede zu erfassen zwischen Formen der Zusammensetzung. Wenn Sie mit einer der (immensen) Klasse von Fällen, wo diese Art von IO ist unangemessen ist, werfen Sie einen Blick auf enumerator
, conduit
und co., Alle wunderbar.
Können Sie den Code anzeigen, in dem Sie 'hClose' selbst verwenden? Es klingt, als würden Sie es schließen, bevor die Eingabe erforderlich war. –