Axel Simon wrote, in response to Keean Schupke > > dbConnectWith :: DbName -> (DbHandle -> IO Result) -> Result > > dbConnectWith name workFn = do > > handle <- dbConnectTo name > > workFn handle `finally` dbDisconnect handle > > > > In this way you avoid finalizers... and everthing is safe providing you > > only export the "with" style functions from the library... Here's an > > example from the library, the connect function: > > I suppose you meant to write "result" rather than "Result". This style > of functions is only safe if the user ensures that DbHandle is never > returned as part of the result. You should have that in your > documentation.
It seems using types to enforce the policy that a data base handle cannot ever `leak' out might be a better idea, in Haskell. It is quite straight-forward to do so: cf. the design of the ST monad guarantees that an STRef cannot `leak' out in the result of runST. Monadic Regions (implemented in Haskell) generalize the idea to multiple nested regions: a pointer (or any other resource, e.g., a database cursor) allocated in one region can be used in nested regions but cannot leak outside of the region that created it (Or, to be more precise, cannot be used outside -- and so, can be safely deallocated when the region is exited). Incidentally, the difficulty with finalizers was precisely the argument for using enumerators rather than cursors in database APIs. Takusen has implemented that idea; takusen currently supports Sqlite, PostgreSQL and Oracle, has a test suite. Its performance test shows that takusen can retrieve 2 million rows from a table without running out of memory. _______________________________________________ Haskell mailing list Haskell@haskell.org http://www.haskell.org/mailman/listinfo/haskell