
David Roundy wrote:
On Tue, Apr 22, 2008 at 7:54 PM, John Meacham
wrote: On Tue, Apr 22, 2008 at 07:45:38PM -0700, Don Stewart wrote:
Finding a good type that encourages the kind of "correctness" approach to handling errors that we like in Haskell would be good though -- if we can improve safety, cheaply, let's do it!
It seems more verbose and ambiguous than safe, because now you have to look up the documentation to figure out what the difference between (Left (ExitSuccess,s)) and (Right s) is, taking up precious, precious mindspace to remembering it and introducing another place a bug can be introduced. Code clarity does a lot more for correctness (and debugability) than dubious measures to improve some idea of safety.
Personally, I'd rather have a version that just throws an exception when the exit code is non-zero. As Duncan mentioned, this is usually what you want to do. Given that the IO monad already has pretty nice (and flexible) error handling, and that this is only a convenience function, which is easily implemented in terms of createProcess, it seems like we should make it actually be convenient. Using Either for error handling means that we can't use this for "simple" cases where the right thing is to fail when the function fails. Using a tuple as the output means that for "simple" cases, folks will almost always do the wrong thing, which is to ignore errors.
Ok, here's the new proposal. readProcess :: FilePath -- ^ command to run -> [String] -- ^ any arguments -> String -- ^ standard input -> IO String -- ^ stdout + stderr readProcessMayFail :: FilePath -- ^ command to run -> [String] -- ^ any arguments -> String -- ^ standard input -> IO (ExitCode,String) -- ^ exitcode, and stdout + stderr It turns out to be dead easy to bind stderr and stdout to the same pipe. After a couple of minor tweaks the following now works: createProcess (proc cmd args){ std_out = CreatePipe, std_err = UseHandle stdout } So now we have: Prelude System.Process> readProcessMayFail "ls" ["/foo"] "" (ExitFailure 2,"ls: /foo: No such file or directory\n") Prelude System.Process> readProcess "ls" ["/foo"] "" *** Exception: readProcess: ls: failed Look ok? Incedentally, for those that know of such things, should readProcess do the same signal management that system currently does? That is, ignore SIGINT and SIGQUIT in the parent and restore them to the default in the child? Cheers, Simon