[Haskell-beginners] lazy IO in readFile

Stephen Blackheath [to Haskell-Beginners] mutilating.cauliflowers.stephen at blacksapphire.com
Sun May 16 07:03:03 EDT 2010


Andrew,

On 15/05/10 11:57, Andrew Sackville-West wrote:
> I'm having trouble determining how to put this into the existing
> context of a string of filter's and maps where the contents of the
> file are used in a predicate to a filter. (if you really want you can
> look at my ridiculous code at
> http://git.swclan.homelinux.org/rss2email.git)

I took a look.  You've got a list of items and you want to check each
one against your 'seen it' file.  I'm not sure what your requirements
are but currently the whole file gets read into memory.  So, sticking
with that, here's _a_ way to do it (with a Set, which gives a faster
lookup):

import Control.Exception
import Data.Set (Set)
import qualified Data.Set as S
import System.IO.Error
import Prelude hiding (catch)


-- | Return "seen it" predicate
readHistory :: FilePath -> IO (String -> Bool)
readHistory fn = do
    hist <- withFile fn ReadMode $ \h -> fetchLines h S.empty
    return (`S.member` hist)
  where
    fetchLines h hist = do
        l <- hGetLine h
        fetchLines h $! S.insert l hist
      `catch` \exc ->
        if isEOFError exc
            then return hist
            else throwIO exc

This is completely strict.  The $! is there to make sure we're keeping a
set in memory, not a chain of inserts (though the inserts wouldn't
actually take up any more memory than the set does).  I haven't tried
compiling this.


Steve


More information about the Beginners mailing list