lazy io - reading files with references to other files in haskell -
i trying expand regular markdown ability have references other files, such content in referenced files rendered @ corresponding places in "master" file.
but furthest i've come implement
createf :: ftree -> io string createf null = homecoming "" createf (node f children) = ifnexists f (_id f) (do childstrings <- mapm createf children withfile (_path f) readmode $ \handle -> fc <- lines <$> hgetcontents handle homecoming $ merge fc childstrings)
ifnexists
helper can ignored, real problem happens in reading of handle, returns empty string, assume due lazy io.
i thought utilize of withfile filepath readmode $ \handle -> {-do stutff-}hgetcontents handle
right solution i've read fcontent <- withfile filepath readmode hgetcontents
bad idea.
another thing confuses me function
createft :: file -> io ftree createft f = ifnexists f null (withfile (_path f) readmode $ \handle -> allow thisparse = fparse (_id f :_parents f) children <-rights . map ( thisparse . trim) . lines <$> hgetcontents handle c <- mapm createft children homecoming $ node f c)
works charm.
so why createf
homecoming empty string?
the whole project , directory/file test can found @ github
here datatype definitions
type id = string info file = file {_id :: id, _path :: filepath, _parents :: [id]} deriving (show) info ftree = null | node { _file :: file , _children :: [ftree]} deriving (show)
as suspected, lazy io problem. here's (awful) rule have follow utilize without going totally nuts:
a withfile
computation must not finish until (lazy) i/o required evaluate result has been performed.
if forces i/o after handle closed, not guaranteed error, though nice. instead, undefined behavior.
you break rule return $ merge fc childstrings
, because value returned before it's been evaluated. can instead vaguely like
let retval = merge fc childstrings deepseq retval $ homecoming retval
an arguably cleaner alternative set rest of code relies on results withfile
argument. real reason not if bunch of other work results after you're finished file. example, if you're processing bunch of different files , accumulating results, want sure close each of them when you're done it. if you're reading in 1 file , acting on it, can leave open till you're finished.
by way, submitted feature request ghc team see if might willing create these kinds of programs more fail useful error messages.
updatethe feature request accepted, , such programs much more produce useful error messages. see what caused "delayed read on closed handle" error? details.
haskell lazy-io
No comments:
Post a Comment