
On Wed, Sep 29, 2010 at 7:21 AM, Michael Snoyman
I think this approach is not possible without involving some fairly ugly unsafeInterleaveIO/unsafePerformIO calls. A simple example using a common web programming example: support I have a multi-user blog site, where each user can have multiple entries. I would model this using standard Haskell datatypes as:
data Entry = Entry { title :: String, content :: String } data Blogger = Blogger { name :: String, entries :: [Entry] }
Obviously we'll need some kind of blogger loading function:
getBloggerByName :: String -> IO Blogger
Either this will load up all entries (a potentially incredibly costly operation) or use unsafe IO down the road. Especially when using database connections, this can be incredibly bad: the connection could be closed, the SQL statement could be reused by another request, etc.
It may be possible to tag those data fields that are not to be loaded on the spot. For example,
data Entry = Entry { title :: String, content :: String } data Blogger db = Blogger { name :: String, entries :: OnDB db [Entry] }
class Monad db => Database db where data OnDB db :: * -> * fetch :: OnDB db a -> db a fetchSome :: Criteria a -> OnDB db [a] -> db [a]
newtype InMemory a = InMemory a instance Database InMemory where newtype OnDB db a = OnDBMem a fetch (OnDBMem x) = return x fetchSome = ...
instance Database SQL where ...
Cheers, -- Felipe.