Friday, 15 March 2013

lazy io - reading files with references to other files in haskell -



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.

update

the 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