
"Matthew Brecknell"
enumLines :: (a -> String -> Either a a) -> a -> FilePath -> IO a enumLines iter accum filename = do h <- openFile filename ReadMode flip fix accum $ \iterate accum -> do try_line <- try (hGetLine h) case try_line of Left e -> hClose h >> return accum Right line -> do case iter accum line of Left accum -> hClose h >> return accum Right accum -> iterate accum
Another variation, enabling multiple iteratees (like a state machine), exception propagation, and no flip fix :)
newtype Iterator a = Iterator (a -> String -> (a,Maybe (Iterator a)))
enumLines :: Iterator a -> a -> FilePath -> IO (a,Maybe Exception) enumLines iterator start filename = do h <- openFile filename ReadMode let f (Iterator iter) accum = do try_line <- try (hGetLine h) case try_line of Left e -> hClose h >> return (accum,Just e) Right line -> do case iter accum line of (acc',Nothing) -> hClose h >> return (acc',Nothing) (acc',Just cont) -> f cont acc' f iterator start -- Feri.