I have an expensive IO action I want to memoise and run lazily... which hasn't actually been written yet, I'm thinking in generalities at the moment, but specifically it's going to be a HTTP fetch (which means I still need to look into how to do HTTP stuff in Haskell too, but I assume there's a library for it somewhere)... I want it to only download the pages I actually want to look at, and memoise them so I don't download the same page twice.
So, I thought I'd do something like the list-of-lazy-values thing for pure functions:
- Code: Select all
-- f :: Int -> a
fMemoised = let memo = map f [0..] in (memo !!)
Now, I know it's possible to do something like this, because it's basically what interact does... it doesn't read the stdin all at once, you can read the first bit, and leave the rest being lazy (just try "interact id" in ghci)... so I'd like to get a [String] that nominally contains all the pages, but will only actually download them when I try to access those Strings.
The closest I've seen is sequence, but that isn't lazy... if I try something like:
- Code: Select all
-- downloadPage :: Int -> IO String
-- processPages :: [String] -> something useful
main = do
let downloaders = map downloadPage [1..10]
pages <- sequence downloaders
let result = processPages pages
But of course, I'm not tied to this particular way of doing it, and any other way that'll let me lazily download the pages would be just as good.
Is there any way to do this without just making processPages an IO action, and putting all the laziness handling in there?
