
My question is this: how do I change my program to make StringMap a lazily-loaded structure based on getStringMapValue without changing f?
You can't, because 'f' has a pure signature, but you want it to run network operations, which are not pure. You could say it's logically pure if you guarantee that no one else is modifying the DB while your program is running, and you are willing to completely abort on a network error, in which case there's a hack called unsafeInterleaveIO. However, I'm guessing no one is going to recommend actually doing that. The Prelude getContents function does that and it gets a lot of flak for poor error handling, not closing the handle when you want it to, etc. Talking over the network will have all those same problems. If you want to operate over a large structure and hide the fetching part, you can look into the iteratee stuff. Basically you would define a function that opens a socket, passes chunks of data to a passed in pure iteratee function, and closes the socket afterwards. If you have a random access Map then I can't think of anything more elegant than the standard imperative "lookup :: Key -> RemoteMap -> IO Val" possibly with caching. Put the reading strategy in an IO function, and the rest of the processing in passed-in pure functions.