The addIOError functions are very useful. Quite often an error is generated by throwErrno in a function which is a long way from the one which the consumer of a library initially called; for example when I get an error from Directory.renameFile I want the error message to say "Directory.renameFile" and contain the filename that I passed to renameFile. So you'd implement renameFile as
renameFile file1 file2 = addIOErrorLocAndPath "Directoy.renameFile" file1 $ do ...
I understand what you want to achieve, but I am not really sure yet that it the right way. Basically, you propose to maintain an implicit state that stores information that should go into the next error message, right?
No, nothing that complicated. The implementation is just something like addIOErrorLocAndPath loc path io = catch io (\err -> ioError err{loc=loc,path=path}) but we can't write that at the moment because the IOError type is abstract. Perhaps the right thing to do is to push this down to a lower level and provide a family of functions like replaceIOErrorPath :: IOError -> FilePath -> IOError or even to specify that IOError is a record type with at least certain fields. I don't mind which we do, as long as there's a portable way to modify these fields in an IOError.
Can't this lead to unexpected results unless everybody is very disciplined about how to use this feature. Especially, when a function has more than one potential failure point, I am concerned that the context may be misleading.
Yes, it could lead to unexpected results if used incorrectly. You need to establish a convention for the location/path information in an IOError. But the current situation is inconvenient - to do the right thing you have to pass this information around in order to plug it into a throwErrno call that might be several layers deep. And there's currently no way to plug in the path info at all. I prefer to attach the information where it is known, using something like addIOErrorLocAndPath - that's a more modular approach, after all. Cheers, Simon
The implementation is just something like
addIOErrorLocAndPath loc path io = catch io (\err -> ioError err{loc=loc,path=path})
This reminds me of _scc_: 1) We're annotating the code with programmer-meaningful annotations which are then used at runtime to help them understand program behaviour. 2) It has the same nested behaviour as _scc_ 3) Just as stacks of cost centres are useful for profiling, it'd be useful to have stacks of error locations. When you print an IOError, you'd get a list of (nested) error locations - it'd feel a lot like the stack dumps you get from Java. (It'd also be useful to have a function like this in non-monadic code. Implementation should be easy and I think the semantics is straightforward.) -- Alastair Reid reid@cs.utah.edu http://www.cs.utah.edu/~reid/
participants (2)
-
Alastair David Reid -
Simon Marlow