|
Imperative Object Destruction: msg#00036lang.haskell.general
C++ provides a convenient mechanism for cleaning up stuff, the destructor, which is guaranteed to get called when an object passes out of scope (or something). I'm wondering how to make a Haskell equivalent for imperative code. For instance, consider a simple file API, with these operations: open: given a string (the filename), open an existing file with that name, return a file-handle (or fail) count: given a file-handle, get the length of the file read: given a file-handle, offset into the file and a number of bytes, read the file returning a list of bytes (or fail) write: given a file-handle, offset into the file and a list of bytes, write the bytes to the file at the offset close: given a file-handle, close the handle In C++ I could simply create an OpenFile class, with the close operation in the destructor. The actual operations would be hidden from OpenFile's clients. I'd like to represent this API in Haskell so that the type-rules guarantee that in any imperative action of type 'IO a', 1. every opened file gets closed exactly once 2. no read or write operations are performed on file-handles that have not yet been opened, or that have already been closed. My first guess was to create a function that encapsulated the entire life-cycle of the file, passing in a function that would represent whatever one wished to do on the file: count :: Handle -> IO Integer read :: (Integer,Integer) -> Handle -> IO [Byte] write :: (Integer,[Byte]) -> Handle -> IO () withFile :: (Handle -> IO a) -> String -> IO a 'withFile operation name' would open the file called 'name', perform the operation 'operation', and then close the file. So for instance, to get the length of a file named "/home/ashley/foo": withFile count "/home/ashley/foo" Trouble is, one can easily pass a return function to withFile to get ahold of the handle after it's been closed. My second guess was to use a special type to represent an imperative operation that needed a handle: read :: (Integer,Integer) -> HandleOperation [Byte] write :: (Integer,[Byte]) -> HandleOperation () withFile :: HandleOperation a -> String -> IO a Of course, I'd then need to provide functions to compose/concatenate HandleOperation values. But I can't help thinking this problem is already well-known and there's a straightforward solution... -- Ashley Yakeley, Seattle WA |
|
| <Prev in Thread] | Current Thread | [Next in Thread> |
|---|---|---|
| Previous by Date: | List types: 00036, Richard |
|---|---|
| Next by Date: | RE: Imperative Object Destruction: 00036, Simon Peyton-Jones |
| Previous by Thread: | List typesi: 00036, Richard |
| Next by Thread: | RE: Imperative Object Destruction: 00036, Simon Peyton-Jones |
| Indexes: | [Date] [Thread] [Top] [All Lists] |
| News | FAQ | advertise |