RE: [Haskell-cafe] Exceptions during exception unwinding
1254389201.7656.3.ca...@localhost Content-Type: text/plain; charset=Windows-1252 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 On Thu=2C 2009-10-01 at 03:29 +=2C Brian Bloniarz wrote: I.e. why does an exception raised during exception handling get propagated past the exception that triggered the handler? Because it's the obvious and sensible thing to do and it what every other mainstream language with exceptions does. Good to know ... C++ (the mainstream language I'm most familiar with) treats throwing from a destructor during unwinding as a fatal error. bracket openSomeHandle closeSomeHandle doAction Then catch and ignore the exception from closeSomeHandle (though not all exceptions or you'd block ^C etc). That said=2C how will you know that closeSomeHandle ever works if you always ignore any exceptions it raises? I was suggesting having bracket ignore exceptions from closeSomeHandle when doAction threw=2C not that it'd ignore any exceptions from closeSomeHandle. It's only the case where bracket has 2 exceptions to choose from that's ambiguous=2C and I'm saying that there's a fair amount of code out there that'd prefer to see the first one. Your point about ^C gets us i= nto an even grayer area -- maybe code would prefer to propagate whichever of the 2 exceptions is asynchronous=2C or define a criterion to choose which exception is more serious=2C who knows. All these behaviors are easy to implement using the building blocks that Control.Exception exports right now=2C you're right. So I'm free to build my own bracket variants with different behavior and that's what I'll do. I was just wondering if the default behavior that bracket/onException provide (which are themselves built from catch/block/unblock) is the one that most people want. Thanks=2C -Brian =0A= _=0A= Microsoft brings you a new way to search the web. Try Bing=99 now=0A= http://www.bing.com?form=3DMFEHPGpubl=3DWLHMTAGcrea=3DTEXT_MFEHPG_Core_ta= gline_try bing_1x1= ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions during exception unwinding
Sorry for the garbled post, this should hopefully be plain text: On Thu, 2009-10-01 at 03:29 +, Brian Bloniarz wrote: I.e. why does an exception raised during exception handling get propagated past the exception that triggered the handler? Because it's the obvious and sensible thing to do and it what every other mainstream language with exceptions does. The behaviour you want, to automatically discard any exceptions raised in the handler and to always re-raise the original exception can be implemented using the current semantics, but the reverse is not true. Good to know ... C++ (the mainstream language I'm most familiar with) treats throwing from a destructor during unwinding as a fatal error. I was suggesting having bracket ignore exceptions from closeSomeHandle when doAction threw, not that it'd ignore any exceptions from closeSomeHandle. It's only the case where bracket has 2 exceptions to choose from that's ambiguous, and I'm saying that there's a fair amount of code out there that'd prefer to see the first one. Your point about ^C gets us into an even grayer area -- maybe code would prefer to propagate whichever of the 2 exceptions is asynchronous, or define a criterion to choose which exception is more serious, who knows. All these behaviors are easy to implement using the building blocks that Control.Exception exports right now, you're right. So I'm free to build my own bracket variants with different behavior and that's what I'll do. I was just wondering if the default behavior that bracket/onException provide (which are themselves built from catch/block/unblock) is the one that most people want. Thanks, -Brian _ Microsoft brings you a new way to search the web. Try Bing™ now http://www.bing.com?form=MFEHPGpubl=WLHMTAGcrea=TEXT_MFEHPG_Core_tagline_try bing_1x1___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions during exception unwinding
Exception handling code should generally be assumed to work, so if something goes wrong there you would normally like to know about it. Also, there is nothing preventing you from wrapping the rescue code in further exception handling, however, if the initial error were raised upon encountering a second error, you would not be able to choose to handle the second error. This is how I see it anyway. On Thu, Oct 1, 2009 at 11:29 AM, Brian Bloniarz phun...@hotmail.com wrote: I had a question about onException friends: what's the rationale for having: (error foo) `onException` (error bar) give bar and not foo? I.e. why does an exception raised during exception handling get propagated past the exception that triggered the handler? Most examples I can think for exception unwinding code would prefer the original exception be propagated -- for example, HDBC has a function which rolls back a DB transaction on exception; it implements it like so: withTransaction conn func = do r - onException (func conn) doRollback commit conn return r where doRollback = -- Discard any exception from (rollback conn) so original -- exception can be re-raised Control.Exception.catch (rollback conn) doRollbackHandler doRollbackHandler :: SomeException - IO () doRollbackHandler _ = return () IMHO, it'd be easier to just write: withTransaction conn func = do r - onException (func conn) (rollback conn) commit conn return r This same argument applies to bracket, bracket_, bracketOnError finally; even the common: bracket openSomeHandle closeSomeHandle doAction If some error arises during doAction, there's a chance closeSomeHandle might fail (even a good chance, given that exception unwinding paths are usually poorly tested), and probably doAction has more accurate information about what went wrong than closeSomeHandle. This is just a thought; I hadn't seen this discussed somewhere. I know for example that Java has the same approach as the current Control.Exception, so there must be good arguments for that too. One that I can think of: using onException to rethrow an exception as a different type, though that's what mapException is for, correct? Thanks, -Brian _ Microsoft brings you a new way to search the web. Try Bing™ now http://www.bing.com?form=MFEHPGpubl=WLHMTAGcrea=TEXT_MFEHPG_Core_tagline_try bing_1x1___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions during exception unwinding
On Thu, 2009-10-01 at 03:29 +, Brian Bloniarz wrote: I had a question about onException friends: what's the rationale for having: (error foo) `onException` (error bar) give bar and not foo? I.e. why does an exception raised during exception handling get propagated past the exception that triggered the handler? Because it's the obvious and sensible thing to do and it what every other mainstream language with exceptions does. The behaviour you want, to automatically discard any exceptions raised in the handler and to always re-raise the original exception can be implemented using the current semantics, but the reverse is not true. Most examples I can think for exception unwinding code would prefer the original exception be propagated Then do not rethrow a different exception. This same argument applies to bracket, bracket_, bracketOnError finally; even the common: bracket openSomeHandle closeSomeHandle doAction If some error arises during doAction, there's a chance closeSomeHandle might fail (even a good chance, given that exception unwinding paths are usually poorly tested), and probably doAction has more accurate information about what went wrong than closeSomeHandle. Then catch and ignore the exception from closeSomeHandle (though not all exceptions or you'd block ^C etc). That said, how will you know that closeSomeHandle ever works if you always ignore any exceptions it raises? For example in the case of your database transaction, having the transaction fail and roll back is something your application may be set up to handle. But transation failing during the rollback may be much more catastrophic and may want to be treated differently. If it fails in the rollback it might be leaking resources and at the very least you may want to log it differently from just a transaction that was successfully rolled back. This is just a thought; I hadn't seen this discussed somewhere. I know for example that Java has the same approach as the current Control.Exception, so there must be good arguments for that too. One that I can think of: using onException to rethrow an exception as a different type, though that's what mapException is for, correct? mapException is for the case of exceptions raised by pure code. As you say, being able to rethrow a different kind of exception, or simply handle the exception there and then are useful. I think using onException is the best one for your use case. If you really really want to ignore an exception raised by rollback then you have the tools available to do so. As I mentioned earlier do not just catch and discard all exceptions, see: http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#4 Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Exceptions during exception unwinding
I had a question about onException friends: what's the rationale for having: (error foo) `onException` (error bar) give bar and not foo? I.e. why does an exception raised during exception handling get propagated past the exception that triggered the handler? Most examples I can think for exception unwinding code would prefer the original exception be propagated -- for example, HDBC has a function which rolls back a DB transaction on exception; it implements it like so: withTransaction conn func = do r - onException (func conn) doRollback commit conn return r where doRollback = -- Discard any exception from (rollback conn) so original -- exception can be re-raised Control.Exception.catch (rollback conn) doRollbackHandler doRollbackHandler :: SomeException - IO () doRollbackHandler _ = return () IMHO, it'd be easier to just write: withTransaction conn func = do r - onException (func conn) (rollback conn) commit conn return r This same argument applies to bracket, bracket_, bracketOnError finally; even the common: bracket openSomeHandle closeSomeHandle doAction If some error arises during doAction, there's a chance closeSomeHandle might fail (even a good chance, given that exception unwinding paths are usually poorly tested), and probably doAction has more accurate information about what went wrong than closeSomeHandle. This is just a thought; I hadn't seen this discussed somewhere. I know for example that Java has the same approach as the current Control.Exception, so there must be good arguments for that too. One that I can think of: using onException to rethrow an exception as a different type, though that's what mapException is for, correct? Thanks, -Brian _ Microsoft brings you a new way to search the web. Try Bing™ now http://www.bing.com?form=MFEHPGpubl=WLHMTAGcrea=TEXT_MFEHPG_Core_tagline_try bing_1x1___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Wed, Sep 17, 2008 at 09:54:13PM -0700, Ryan Ingram wrote: Better is this: data MalformedAddressException = MalformedAddressException String deriving (Show, Typeable) throwDynIO x = throwIO (DynException $ toDyn x) You are right. Anyway the DynException will not be needed in the future because you can throw arbitrary types directly.. But if you change the code the type checker won't fail, you'll keep catching the old user error while the new dyn type is beeing thrown. That's the mess. The only thing to do is whenever you start using inet_addr implement an HUnit test to ensure it still throws a user exception.. That's the only reliable way to get notified if the behaviour changes.. But the strength of haskell is that we don't have to write tests for everything because the type checker will do most work for us.. Another solution would be telling the compiler that the exception beeing caught must be thrown within this thread... But that's not possible with the new SomeException either. So my result is that Exceptions should not be used here (?) or there should be an alternative function.. Is that feasable to have to functions so that you can choose? inet_addr_ThrowEx ? inet_addr_Maybe ? Java would have recignized if the exception type changes from user error to dyn type. Haskell can't :-( Marc Weber ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Sun, Jul 27, 2008 at 07:23:14PM +0200, Adrian Neumann wrote: Hello, I think it'd be nice if the compiler could warn me if there are any exceptions which I'm not catching, similar to checked exceptions in Java. Does anyone know of a possibility to do that in Haskell? He, I have found a use case for your request: from network inet_addr :: String - IO HostAddress inet_addr ipstr = do withCString ipstr $ \str - do had - c_inet_addr str if had == -1 then ioError (userError (inet_addr: Malformed address: ++ ipstr)) else return had -- network byte order from HAppS-Server: host - Exception.catch (inet_addr uri)-- handles ascii IP numbers (\_ - getHostByName uri = \host - case hostAddresses host of [] - return (error no addresses in host entry) (h:_) - return h) Very bad because this catches Exceptions thrown by trowTo as well, doesn't it? On the other hand just catching the UserError can be useless if the maintainers decide to throw a custom Exception in the future (which can and should be done in the future when extensible exceptions are standard?) In this case I would miss this update and miss to update the code. If we could only catch exceptions. Using Either would be another choice here. But it would lead to much more code. Anyway It think using Either is better because it can't lead to code as shown above. Another nice use case for Exceptions are timouts as implemented by HAppS as well. However I must conclude that a function call including the code above can just absorb my exception and rethrow another one (or in a worse case continue?) So maybe I have to change the TimOut code to do a forever (throwTo threadId TimOutException) to make sure it quits as fast as possible? This could lead to different trouble. So I think using Either is the best option although there is some more code to write. Marc Weber ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
Better is this: data MalformedAddressException = MalformedAddressException String deriving (Show, Typeable) throwDynIO x = throwIO (DynException $ toDyn x) -- in inet_error ... throwDynIO (MalformedAddressException blah blah) ... -- in HAppS-Server ... Exception.catchDyn (inet_addr uri) (\(MalformedAddressException s) - ...) -- ryan On Wed, Sep 17, 2008 at 5:51 PM, Marc Weber [EMAIL PROTECTED] wrote: On Sun, Jul 27, 2008 at 07:23:14PM +0200, Adrian Neumann wrote: Hello, I think it'd be nice if the compiler could warn me if there are any exceptions which I'm not catching, similar to checked exceptions in Java. Does anyone know of a possibility to do that in Haskell? He, I have found a use case for your request: from network inet_addr :: String - IO HostAddress inet_addr ipstr = do withCString ipstr $ \str - do had - c_inet_addr str if had == -1 then ioError (userError (inet_addr: Malformed address: ++ ipstr)) else return had -- network byte order from HAppS-Server: host - Exception.catch (inet_addr uri)-- handles ascii IP numbers (\_ - getHostByName uri = \host - case hostAddresses host of [] - return (error no addresses in host entry) (h:_) - return h) Very bad because this catches Exceptions thrown by trowTo as well, doesn't it? On the other hand just catching the UserError can be useless if the maintainers decide to throw a custom Exception in the future (which can and should be done in the future when extensible exceptions are standard?) In this case I would miss this update and miss to update the code. If we could only catch exceptions. Using Either would be another choice here. But it would lead to much more code. Anyway It think using Either is better because it can't lead to code as shown above. Another nice use case for Exceptions are timouts as implemented by HAppS as well. However I must conclude that a function call including the code above can just absorb my exception and rethrow another one (or in a worse case continue?) So maybe I have to change the TimOut code to do a forever (throwTo threadId TimOutException) to make sure it quits as fast as possible? This could lead to different trouble. So I think using Either is the best option although there is some more code to write. Marc Weber ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Sun, 27 Jul 2008, Adrian Neumann wrote: Hello, I think it'd be nice if the compiler could warn me if there are any exceptions which I'm not catching, similar to checked exceptions in Java. Does anyone know of a possibility to do that in Haskell? Please refer to the long extensible extension thread: http://www.haskell.org/pipermail/libraries/2008-July/010095.html In my posts I sketched possibilities to do that. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Exceptions
Hello, I think it'd be nice if the compiler could warn me if there are any exceptions which I'm not catching, similar to checked exceptions in Java. Does anyone know of a possibility to do that in Haskell? Adrian PGP.sig Description: Signierter Teil der Nachricht ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
I don't really think this is possible: consider asynchronous exceptions and throwTo. http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control-Exception.html#v%3AthrowTo Since it can throw just *any* exception into thread. And this thread might not be aware that anyone can throw him anything. Therefore it is not possible to catch it while compiling it's code. But Maybe I'm Just wrong. Christopher Skrzętnicki 2008/7/27 Adrian Neumann [EMAIL PROTECTED]: Hello, I think it'd be nice if the compiler could warn me if there are any exceptions which I'm not catching, similar to checked exceptions in Java. Does anyone know of a possibility to do that in Haskell? Adrian ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
aneumann: Hello, I think it'd be nice if the compiler could warn me if there are any exceptions which I'm not catching, similar to checked exceptions in Java. Does anyone know of a possibility to do that in Haskell? Adrian You could provide exception-safe wrappers for the functions you use, that catch any exception and flatten it to an Either type (or something similar). Then GHC's usual coverage checking will enforce the handling. import qualified System.IO import Control.Exception maybeReadFile :: FilePath - IO (Maybe String) maybeReadFile f = handle (\_ - return Nothing) (Just `fmap` System.IO.readFile f) {- *A maybeReadFile /tmp/DOESNOTEXIST Nothing -} main = do mf - maybeReadFile DOESNOTEXIST case mf of Nothing - return () Just s - print s The ability to control exceptions seems like something we should have more solutions for. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
[+RTS -xc] A major problem with this that I notice is that it dumps the stack whenever any exception is raised, which is a big pain if your program does IO and regularly raises and catches exceptions as part of normal operation. A big improvement would be to only dump the backtrace if the exception was uncaught and caused the program to abort. Agreed. I wrote the -RTS +xc code several years ago, and thought that what you describe would be much nicer. But this would have involved quite a bit more hacking of the RTS. At the point the exception is thrown, the backtrace is just sitting there waiting to be dumped. But once it's thrown this information is lost. I imagined wrapping up the backtrace information into a data structure and including that as an argument to the exception, so that the primitive catch operation would receive a backtrace in addition to the exception itself; then the backtrace could be dumped to stderr or whatever by the default toplevel handler. In the end I didn't have the motivation to implement this, and I don't have the same contact with the GHC codebase any more. I'd be happy to help anyone who wanted to add this, though, or for someone just to go ahead and do it... --KW 8-) ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: [Haskell-cafe] Exceptions
Actually GHC does exactly that when you compile with -prof -auto-all. Then if you run with +RTS -xc, you get a backtrace of sorts. (I have not tested this recently!) The backtrace is not yet reified into a data structure that can be examined, but that'd be quite doable if someone wanted to try. The downside is that -prof makes many optimisations work less well, and all modules must be compiled this way. Simon | -Original Message- | From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of MR | K P SCHUPKE | Sent: 01 October 2004 18:29 | To: [EMAIL PROTECTED]; [EMAIL PROTECTED] | Cc: [EMAIL PROTECTED]; [EMAIL PROTECTED] | Subject: Re: [Haskell-cafe] Exceptions | | But, being able to see the context in which a thunk was constructed would be | extremely useful. | | Yes of course... I was thinking along the lines of what is possible, rather | than what is desirable. If only ghc had a -g (debug) flag like gcc that would | force each funtion to push its entry onto some kind of call stack that would | be returned by exceptions... | | Keean. | ___ | Haskell-Cafe mailing list | [EMAIL PROTECTED] | http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Mon, Oct 04, 2004 at 09:30:22AM +0100, Simon Peyton-Jones wrote: Actually GHC does exactly that when you compile with -prof -auto-all. Then if you run with +RTS -xc, you get a backtrace of sorts. (I have not tested this recently!) The backtrace is not yet reified into a data structure that can be examined, but that'd be quite doable if someone wanted to try. A major problem with this that I notice is that it dumps the stack whenever any exception is raised, which is a big pain if your program does IO and regularly raises and catches exceptions as part of normal operation. A big improvement would be to only dump the backtrace if the exception was uncaught and caused the program to abort. John -- John Meacham - repetae.netjohn ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
I'd be cautious about using exceptions too liberally. When I implemented a Haskell equivalent to traceroute, I wanted to stop sending packets when a certain condition occurred. It was very tempting to throw an exception and catch it at the top level. However, I think the code below is easier for the maintainer (me) to understand. Dominic. sequenceWhile_ :: Monad m = (a - Bool) - [m a] - m () sequenceWhile_ p [] = return () sequenceWhile_ p (x:xs) = x = \c - if (p c) then sequenceWhile_ p xs else return () ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Exceptions
One of the most important features of a modern language is, to me, exceptions. I have found very little coverage of exceptions in Haskell, what what coverage there was seemed to be centered on I/O. One reason I'm asking is this: what to do when pattern matching is incomplete due to an error. For instance, this is a common pattern in my OCaml code: let queuedir_of_type t = match t with foo - /data/queue5 | bar - /data/queue3 | _ - raise (Exception (Invalid type ^ t));; This is often useful when t is something that was originally read from a user. Python has an expressive exception mechanism, where one can catch various different exceptions from a single block of code, etc. So, I have some questions about exceptions in Haskell: 1. Can exceptions be used in pure functions (outside of monads?) 2. How are these exceptions caught and handled aside from using bracket? 3. Can I define my own exception types? 4. Can I write code that can catch and handle multiple different exception types from a single block of code? 5. Is there anything different about working with exceptions in monads? 6. Can I get a stack trace from ghc or hugs if an exception is never caught and thus causes the program to terminate? Thanks! -- John ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
1. Can exceptions be used in pure functions (outside of monads?) Exceptions can be thrown from pure functions, and can be used exactly like in the OCaml example (but in Haskell syntax) Exceptions can only be caught in the IO monad. 2. How are these exceptions caught and handled aside from using bracket? bracket, catch, catchIO 3. Can I define my own exception types? There is a User exception type, I don't think you can define your own completely new exception type. 4. Can I write code that can catch and handle multiple different exception types from a single block of code? Yes but see (1) only in the IO monad 5. Is there anything different about working with exceptions in monads? No. 6. Can I get a stack trace from ghc or hugs if an exception is never caught and thus causes the program to terminate? Stack traces in lazy laguages are not very useful. Best work-around is to produce an explicit call trace by inserting prints into functions... obviously this requires the functions to be in the IOMonad. Things are still odd because of lazyness though. Keean. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Fri, 1 Oct 2004, John Goerzen wrote: 1. Can exceptions be used in pure functions (outside of monads?) No. The Maybe and Either types may make for viable replacements though. -- [EMAIL PROTECTED] ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Friday 01 October 2004 10:57 am, MR K P SCHUPKE wrote: 1. Can exceptions be used in pure functions (outside of monads?) Exceptions can be thrown from pure functions, and can be used exactly like in the OCaml example (but in Haskell syntax) Can you give me a quick example of how exactly I would do that? I'm trying to understand the ghc docs and not quite making it. Thanks! -- John ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
John Goerzen [EMAIL PROTECTED] writes: 1. Can exceptions be used in pure functions (outside of monads?) For the theoretical background of this, see A Semantics for Imprecise Exceptions http://citeseer.ist.psu.edu/196569.html. -- __( Marcin Kowalczyk \__/ [EMAIL PROTECTED] ^^ http://qrnik.knm.org.pl/~qrczak/ ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
6. Can I get a stack trace from ghc or hugs if an exception is never caught and thus causes the program to terminate? Stack traces in lazy laguages are not very useful. Best work-around is to produce an explicit call trace by inserting prints into functions... obviously this requires the functions to be in the IOMonad. Things are still odd because of lazyness though. I don't think this is completely true. What typical Haskell compilers have on their stack is not especially useful because it reveals the context in which something was being evaluated and will depend on details of the compiler, what optimizations it performs, etc. But, being able to see the context in which a thunk was constructed would be extremely useful. Such a context would be more or less equivalent to the context (or 'stack dump') printed when the same program is evaluated strictly - by a Caml compiler, say. I think the York folk have the best story on stack traces - I don't know if non-deterministic exceptions have been integrated into their system - probably so. -- Alastair Reid ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
On Friday 01 October 2004 16:43, John Goerzen wrote: One of the most important features of a modern language is, to me, exceptions. I have found very little coverage of exceptions in Haskell, what what coverage there was seemed to be centered on I/O. There's three things one might call exceptions in Haskell: 1) IOErrors result from IO operations and can be caught in the IO monad. 2) Exceptions result from pure or IO code and can be caught in the IO monad. They are raised by calling raise (in pure code) or raiseIO (in IO code). They are also raised by pattern match failure, calls to error and things like division by zero. They are non-deterministic in the following sense: The expression '(raise exn1) + (raise exn2) :: Int' may raise either exception 'exn1' or exception 'exn2' depending on choice of compiler, optimization options, environment settings, current time of day, phase of moon, etc. It is because of this non-determinism that exceptions can _only_ be caught in the IO monad. Another consequence is that exceptions are not very useful for reporting errors in user input where determinism, reporting errors before starting a long computation, being able to report multiple errors, etc are useful. 3) Error values can be distinguished using the Maybe or Either types and/or using monads. For example, parsing command line arguments might yield: Right 42 or Left Error: can't parse '42.0' - integer expected The advantage of this approach is that the type system tracks where errors can propagate to so you can be confident that error checking is being performed _before_ spending 3 days computing a result and not when you go to write the answer. The disadvantage is that it is a bit tedious - but monads, lifting, etc. help a lot with this. In the following, I'll tak exclusively about the 2nd type (since the other two are obvious). 1. Can exceptions be used in pure functions (outside of monads?) They can be raised in pure functions but can only be caught in IO functions. (If you simply want to change what exception is reported, that can be done in pure code.) 2. How are these exceptions caught and handled aside from using bracket? There is a catch function with type: catch :: IO a - (Exception - IO a) - IO a Built on top of this, are functions to do things like try-finally. One of my favourites is 'bracket' which takes an initial action, a final action and a middle action (in that order) and makes sure that the final action is performed even if the middle action fails. For example: bracket (open /etc/passwd) hClose $ \ h - do cs - hGetContents h mapM crack (lines cs) The strange order of the arguments is to put the initial action (opening the file) next to the final action (closing the file) - which is often a good thing. 3. Can I define my own exception types? Sadly, no. There is only one 'exception type'. You can use dynamics and encode new kinds of exceptions as Strings but that isn't very satisfactory. 4. Can I write code that can catch and handle multiple different exception types from a single block of code? You use standard Haskell pattern matching so, yes, you can catch multiple kinds of exceptions. They're not different types though. 5. Is there anything different about working with exceptions in monads? Use raiseIO instead of raise to raise exceptions. 6. Can I get a stack trace from ghc or hugs if an exception is never caught and thus causes the program to terminate? Sadly, no. -- Alastair Reid ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
But, being able to see the context in which a thunk was constructed would be extremely useful. Yes of course... I was thinking along the lines of what is possible, rather than what is desirable. If only ghc had a -g (debug) flag like gcc that would force each funtion to push its entry onto some kind of call stack that would be returned by exceptions... Keean. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Exceptions
Alastair Reid wrote: 3. Can I define my own exception types? Sadly, no. There is only one 'exception type'. You can use dynamics and encode new kinds of exceptions as Strings but that isn't very satisfactory. But not at all, allowing you to declare your own exception types is *exactly* what using dynamic exceptions is all about. No need for String encodings, we can do far better than that. =) If I have my own type of exceptions, by making that type an instance of Typeable I can use the functions 'throwDyn' and 'catchDyn' instead of the normal 'throw' and 'catch'. That way I can declare exception handlers that only exceptions of a particular type, and just re-raises any other. I could for instance write main = do ... a bunch of computations ... `catchDyn` (\e :: MyExceptionType1 - ... handle exceptions of MyExceptionType1 ...) `catchDyn` (\e :: MyExceptionType2 - ... handle exceptions of MyExceptionType2 ...) `catch` (\e - ... handle exceptions of the built-in Exceptions type ...) (Note that the type annotations on the patterns are not needed if the types can be inferred properly from within the handler. Note also that the Typeable constraint can be automatically derived by ghc with -fglasgow-exts, so no difficulty there either) Check the section about dynamic exceptions at http://www.haskell.org/ghc/docs/latest/html/libraries/base/Control.Exception.html for more info. 4. Can I write code that can catch and handle multiple different exception types from a single block of code? You use standard Haskell pattern matching so, yes, you can catch multiple kinds of exceptions. They're not different types though. But yes they are, see above. Or rather, they can be, or they can be constructors of a common user-defined type, combining common pattern matching with dynamic matching on types. =) 5. Is there anything different about working with exceptions in monads? Use raiseIO instead of raise to raise exceptions. The functions for raising exceptions are called 'throw' and 'throwIO' (and 'throwDyn'), not raise. /Niklas _ The new MSN 8: advanced junk mail protection and 2 months FREE* http://join.msn.com/?page=features/junkmail ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
MR K P SCHUPKE [EMAIL PROTECTED] writes: As for head, I think it's fine that it throws an error because it is specified to be defined for only non-empty lists. But surely it is better to encode this fact in the type system by useing a separate type for non-empty lists. Yes, in principle. But that means you still need to write more and tedious code to deal with it. And there's a question how far you can practically get with this approach. Are you going to discard lists in favor of tuples, just because the type systems can't verify that the index passed to (!!) is witin range? A mechanism for a function to report the caller site would obliviate the need for all this ugliness Unfortunately the cost of this is prohabative as the call stack would have to contain backtrace information. Also due to lazy evaluation the 'call site' may not be what you expect. AFAICS, this disadvantage is shared by all other schemes of labeling call sites. The only difference is that I want to do it automatically (perhaps when a debug option is passed to the compiler) I don't want it for all functions or anything, just the annoying, small, and commonly used leaf functions. Here's what John Meacham had to say: --- Note that pattern matching rather than deconstruction functions have a number of benefits, not just relating to error messages, consider two functions which use the head of their argument. f xs = ... head xs ...=20 g (x:_) = ... x ... now, g is superior to f in several ways,=20 I agree with this. How about constructs like mins = map (head.sort) Is mins = map ((\(x:_)-x).sort) still so superior? Is it really necessary to sacrifice code clarity just to get decent error messages? And how do you extend this approach to 'read' and (!!)? -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Yes, in principle. But that means you still need to write more and tedious code to deal with it. Just because code is tedious does not mean it is not necessary to handle all corner cases. A robust application does not fail when given unexpected input. Are you going to discard lists in favor of tuples, Of course not... You can actually define constrained datatypes where the maximum length is a parameter of the type. Unfortunately in haskell because these values have to be at the type level we end up encoding them as Peano numbers... See Conor McBrides Faking It paper for some examples of how to do this. Also see Oleg, Ralf and My paper Stronly Typed Heterogeneous Lists to se how far you can get with these techniques (we define a heterogeneous list that can be constrained in many ways, including by length, or content type). I guess in a way you are nearly right as these techniques fundamentaly us binary products like (,) - but thats also exactly what any binary constructor including ':' is anyway... The only difference is that I want to do it automatically My point was that you can manually label some functions, but to automatically do it for all functions is going to cause big stack space problems - think about recursive functions... or mutually recursive functions... Keean. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
mins = map ((\(x:_)-x).sort) maybe what you meant was: case sort x of (x:_) - ... do whatever with x ... _ - ... do failure conition ... As I said, if you can _guarantee_ non failure I guess head is okay, but the fact that this thread started with the observation that the error produced by head is difficault to track dow n we must conclude that programmers make mistakes and cannot be trusted to make such guarantees Hence my suggestion to use the type system. Effectively the 'case' forms a guarantee of non-emtyness for the stuff in the case... but you cannot pass this guarantee into functions like 'head' Using the type system to encode such things allows this 'guarantee' to be passed into functions... Keean. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
On Tue, Aug 03, 2004 at 12:51:50PM +0200, Ketil Malde wrote: Is there any easy way (TH?) to amend these to output the line number of the offending caller? It would be a great improvement to see something like Prelude.head : empty list in Foo.hs, line 4711 since programs generally contain many, many calls to functions like these. I include the following file in most files (and always use the C preprocessor): import DarcsUtils ( bug ) #define impossible (bug $ Impossible case at ++__FILE__++:++show (__LINE__ :: Int)++ compiled ++__TIME__++ ++__DATE__) #define fromJust (\m - case m of {Nothing - bug (fromJust error at ++__FILE__++:++show (__LINE__ :: Int)++ compiled ++__TIME__++ ++__DATE__); Just x - x}) Here bug is a function that just calls error with a little prefix explaining that there is a bug in darcs, and would the user please report it. Obviously, defining a head here would be just as easy, but I usually have more trouble with fromJust, which in a few places gets called in internal routines where I *should* know that the data structure has no Nothings, but have been known to make mistakes. I also catch all error exceptions and print a nicer error message, so I use fail and error raw to indicate actual user errors. -- David Roundy http://www.abridgegame.org ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Ketil Malde [EMAIL PROTECTED] writes: Hmm...if I run it through CPP and #define HEAD (\x - if null x then error (__FILE__:__LINE__) else head x) is the __LINE__ resolved at the place of declaration or at the place of usage? According to the C standard, at the position of /usage/ of the macro `HEAD'. Incidentally, cpphs does not yet implement __FILE__ or __LINE__ replacements. Is their usage widespread amongst Haskell users? Regards, Malcolm ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
MR K P SCHUPKE [EMAIL PROTECTED] writes: mins = map ((\(x:_)-x).sort) maybe what you meant was: case sort x of (x:_) - ... do whatever with x ... _ - ... do failure conition ... No, I don't think so. I only want the bug to be reported, and the umatched pattern will do it nicely. Yes, in principle. But that means you still need to write more and tedious code to deal with it. Just because code is tedious does not mean it is not necessary to handle all corner cases. A robust application does not fail when given unexpected input. But if I use head, I should *know* that I never pass it an empty list. Whether head returns a Nothing or just crashes doesn't matter, I have to go and fix my *design*, because it has a bug, and not a corner case that should be handled. Are you going to discard lists in favor of tuples, Of course not... You can actually define constrained datatypes where the maximum length is a parameter of the type. The only difference is that I want to do it automatically My point was that you can manually label some functions, but to automatically do it for all functions is going to cause big stack space problems - think about recursive functions... or mutually recursive functions... Yes, of course. So *my* point is that it would be really nice to write small leaf functions like these with an implicit file/line parameter that identified the caller site, in order to avoid cluttering the code with them. Okay, perhaps I'm not using the type system to its full extent, but I think this is fairly common practice. An easy solution seems to be to use -cpp and add #define head (\(x:_)-x) at the top of the relevant source files. However, I'm not sure how to make this work with the other difficult functions. Another alternative (basically emulating the GHC's behavior in the above case) is #define head (\x - case x of {(x:_) - x; _ - error (head failed at ++__FILE__++:++ show __LINE__)}) It seems difficult to generalize this, though. -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
No, I don't think so. I only want the bug to be reported I think preventing the bug using the type system if possible is a good idea... something that should be encouraged! and not a corner case that should be handled. So if the list depends on user input is not the empty list a corner case of the function on user input? write small leaf functions like these with an implicit file/line This is a good idea - If I have given the impression I am opposed to it then I have not expressed myself very well. I just think where this can be avoided using the type system in the first place is an even better idea. Design by contract is the way forward for large complex systems, and where that contract can be expressed using the type system is a selling point for Haskell in such applications. It seems difficult to generalize this, though. Again for read you can use reads... Sven Panne said: reads is probably what you are looking for: Prelude (reads :: ReadS Integer) [] Prelude (reads :: ReadS Integer) a [] Prelude (reads :: ReadS Integer) 2 [(2,)] Prelude (reads :: ReadS Integer) 123blah [(123,blah)] Keean. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
David Roundy [EMAIL PROTECTED] writes: Here bug is a function that just calls error with a little prefix explaining that there is a bug in darcs, and would the user please report it. Obviously, defining a head here would be just as easy, Cool! The basic trick is just to inline the actual function defintions using CPP macros. I've made macros for most of the troublesome functions, but I can't get it to work for operators (something like `(!!)` doesn't parse, it seems) Any tricks? Unless I'm overlooking something, I could have a file prelude.h containing something like: 8-- import Prelude hiding (head,(!!),read) #define head (\xs - case xs of { (x:_) - x ; _ - bug head __FILE__ __LINE__}) #define at (let {at (y:_) 0 = y; at (y:ys) n = at ys (n-1); at _ _ = bug at __FILE__ __LINE__} in \a x - at a x) #define read (\s - case [ x | (x,t) - reads s, (,) - lex t] of { [x] - x ; _ - bug read __FILE__ __LINE__}) #define fromJust (\x - case x of Just a - a; Nothing - bug fromJust __FILE__ __LINE__) bug c f l = error (Program error - illegal parameters to '++c++', file '++f++', line ++show l) 8-- and just #include prelude.h if/when I want better debugging. No expensive stack frames, no unwanted strictness, and no clutter. Any comments? -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Ketil Malde [EMAIL PROTECTED] writes: Unless I'm overlooking something Which I of course did. #define at (let {at (y:_) 0 = y; at (y:ys) n = at ys (n-1); at _ _ = bug at __FILE__ __LINE__} in \a x - at a x) No prize for spotting the bug here. -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Ketil Malde [EMAIL PROTECTED] writes: import Prelude hiding (head,(!!),read) Any comments? Here's one: I thought this would make it difficult to have other imports of Prelude, hiding other pieces of it (e.g. catch, to avoid ambiguities with Control.Exception.catch) (Also, the definition of 'bug' hinders forces the #include to be after any imports, not sure it's better to have a separate module for it, which would then need to be on the module search path) (I seem to be mainly following up to my own posts, so if somebody asks, I'll take this to a quiet corner at the -cafe :-) -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Two observations: 1. When I recently modified the HaXml XML parser, this is one of the significant changes I made: providing (alterantive) return values based on Either, so that input errors could be handled by the invoking function, without forcing it into the IO monad. I guess that's a vote of agreement. 2. I like to distinguish between expected errors and unexpected errors. Having been burned in the past by using exceptions (not FP), I try to use them only for conditions that are truly unexpected; i.e. _exceptional_. Bad input, IMO, is something that is not unexpected, so I don't really like to handle that via exceptions. #g -- At 13:09 02/08/04 -0700, Evan LaForge wrote: Exceptions are convenient in that you can rely on libraries throwing them instead of prechecking for valid values yourself (for instance, why check that the argument to Char.digitToInt is valid if digitToInt does so already), and you don't have to modify a lot of function signatures. Unfortunately, in the face of lazy evaluation, they can get thrown in unexpected places. Even with Exception.evaluate, or code which is already explicitly sequenced in the IO monad, like t - Exception.evaluate (map Char.digitToInt ['a'..'g']) an exception will only be thrown when you inspect the last element of 't'. (digitToInt confusingly accepts hex digits---shouldn't it be higitToInt then?). So it seems to me that if you are, say, checking input, the options are to handle exceptions from the checking code but expect them to come from the processing code, or decorate all checking code with Rights and Lefts. Problems with the first option are that checking code could also trigger some exceptions, and Prelude functions throw undescriptive errors like user error or low level ones like refuted pattern match and catching them over the entire program means you could stifle a lot of real errors. This implies that you have to make specific exceptions and convert Prelude and library exceptions into yours as low down as possible, which is cluttering but maybe not as cluttering as Either. Problems with the second option are many of the problems that lead to us wanting exceptions in the first place. Using Either seems much simpler and functional-friendly. So then, in what contexts are exceptions appropriate in haskell? ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Graham Klyne [EMAIL PROTECTED] writes: 2. I like to distinguish between expected errors and unexpected errors. Having been burned in the past by using exceptions (not FP), I try to use them only for conditions that are truly unexpected; i.e. _exceptional_. Bad input, IMO, is something that is not unexpected, so I don't really like to handle that via exceptions. I agree, trying to handle exceptions caused by incorrect input is just needless complication, the program should crash, and the calling function should be fixed instead. Common errors that happen to me are: Prelude.head : empty list Prelude.read : no parse andPrelude.(!!) : index too large and so on. Is there any easy way (TH?) to amend these to output the line number of the offending caller? It would be a great improvement to see something like Prelude.head : empty list in Foo.hs, line 4711 since programs generally contain many, many calls to functions like these. -kzm -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Hi - I am just learning Haskell and am far away from exception handling intricacies. However I just recently read an article of Herb Sutter about exception handling in C++ with some rules when to use exception handling - and perhaps these rules might be applicable to Haskell too (article: When and How to Use Exceptions, Herb Sutter, C/C++ Users Journal August 2004, pp. 47 -- 51)? Herb Sutter gave these rules : An error is any failure that prevents a function from succeeding. Three main kind of errors: - a condition that prevents the function from meeting a precondition of another function that must be called (so to say: the caller has to check for preconditions while the function called my use C/C++ asserts to assert the correctness of its preconditions) - a condition that prevents a function from establishing one of its own postconditions (e.g. producing a (valid) return value) - a condition that prevents the function from reestablishing an invariant that it is responsible to maintain (special kind of postcondition mainly found in object oriented code). Any other condition is not an error and shouldn't be reported as one. The code that could cause an error is responsible for detecting and reporting the error otherwise this is a programming mistake. I am not sure if these rules apply to real functional programming but at least they seem to be useable. The point that the caller is responsible for checking the preconditions of functions it is calling is something I also found as a suggestion in using the object oriented language Eiffel. Cheers and best regards Bjoern ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
W licie z wto, 03-08-2004, godz. 13:05 +0200, Bjoern Knafla napisa: Herb Sutter gave these rules : An error is any failure that prevents a function from succeeding. Three main kind of errors: [...] These kinds don't explain much. They don't give a clue which errors to report by exceptions and which by return values, because they don't distinguish the reasons for which a (pre|post)condition can't be fulfilled. And I see no point in distinguishing potential errors on this axis. I divide exceptional situations into 4 groups: 1. Expected error: The result can't be computed from this data; the caller was not supposed to check this beforehand because it would duplicate work of the function, or there would be a race condition, or the design is simpler that way. 2. Program error: The given function was not supposed to be invoked in this way by other parts of the program (with these arguments, or with this external state, in this order wrt. other functions etc.). 3. Out of resource: The function is sorry that it was not able to produce the result due to limited memory or arithmetic precision or similar resources. Not yet supported is also in this group. 4. Impossible error: The function thought this couldn't happen, it must have a bug. This is like 2 in that there is a bug somewhere, but like 1 in that the calling code is probably fine. I/O errors can be expected errors or out of resource conditions, depending on whether they were caused by bad input or by external failure. Group 1 should be reported in Haskell by a distinguished result (Maybe, Either, custom type) or by an exception passed in a suitable monad (well, Maybe is a monad; this could be even the IO monad). Other groups are handled in a similar way. In Haskell they can be reported by a bottom, e.g. 'error' function. It makes sense to catch them on a toplevel of the program or a large unit, and it's good that GHC provides a way to catch them. There may be other actions possible than just aborting the program: report the problem to the user, abort just the given operation, but try to continue other work; save user data before aborting; log the error or report it in an appropriate channel, e.g. output a HTML page in case of a CGI program. Sometimes the same function makes sense in two variants: one which reports an expected error, and another which treats it as a program error. Example: lookup in a dictionary. Sometimes the qualification of an error changes while it is propagated. I haven't thought about all cases, but for example program errors become impossible errors if the caller thought that the arguments it passed were good, and expected errors become program errors if the caller's caller was not supposed to give arguments which cause such problems. The most important distinction is between expected errors, whose way of reporting should be visible in the interface and which should be checked for in the calling code, and program errors, which should be automatically propagated and reported near the toplevel. -- __( Marcin Kowalczyk \__/ [EMAIL PROTECTED] ^^ http://qrnik.knm.org.pl/~qrczak/ ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Exceptions should only really be used for unpredictcable events, I find that the defintion of functions like head is lacking rigor... I would prefer to see: head :: [a] - Maybe a head (a0:_) = Just a0 head _ = Nothing In principle, yes, but in practice, that would be silly. You use head just when you know for sure that the list is non-empty; if it is not, it's a program error for head, and an impossible error for the caller. Consider: f (head xs) -- old style vs f (case head xs of Some x - x; None - error whoops) -- Schupke style It should be clear that this function would never be used - if head had this signature, programmers would just write f (case xs of (x:_) - x; [] - error whoops) -- direct style --KW 8-) ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
f (case xs of (x:_) - x; [] - error whoops) -- direct style Yup, this is how I do it... I never use head! I like to pass failures back up to the level where some kind of sensible error message can be generated. In your example the error is no better than with 'head' - the point is a Nothing can be 'caught' outside of an IO monad. I would suggest using the type system as I said earlier so: toNonEmptyList :: [a] - Maybe (NonEmpty a) toNonEmptyList (a0:_) = Just (NonEmpty a) toNonEmptyList _ = Nothing Then redefine head: head :: NonEmpty a - a head (NonEmpty (a0:_)) = a0 Keean/ ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
Prelude.head : empty list Prelude.read : no parse andPrelude.(!!) : index too large and so on. Is there any easy way (TH?) to amend these to output the line number of the offending caller? In a program of any size, I usually avoid using these functions and instead define functions like: --| 1st arg is error message for empty lists head' :: Doc - [a] - a --| 1st arg is description of kind of thing in list -- Reports error if length of list /= 1 unique :: Doc - [a] - a etc. Another approach is to use a function: inContext :: String - a - a (implemented using mapException) like this: inContext evaluating expression (eval env e) to transform an exception of the form: error Division by zero into error Division by zero while evaluating expression Since the inContext function is rather like ghc's profiling function 'scc', it would be nice if ghc had a command-line flag to insert a call to inContext everywhere that it inserts a call to scc when you use -prof-all. (Of course, you'd probably take a big stack-space hit from doing so since the chain of calls to inContext is equivalent to the stack you would expect if using call by value without tail call optimization. -- Alastair Reid ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
A lot of programming errors come from failure to correctly validate. This was actually nicely illustrated in my program: I assumed that digitToInt accepted '0'..'9' and wanted to rely on it throwing. After puzzling over out of range errors (other functions expected digitToInt to be in the 0..9 range) I figured it out and inserted an explicit check. Unfortunately there is no static check for pre and post conditions, unless you manually add them to the type system, as you suggest. But that's work ;) Wrting a monad bind for Either that returns Left immediately and binds Right would make Either style error propagation easier. But it seems like it would over sequence: do a' - checka a b' - checkb b return $ process a' b' is rather messier looking than 'process (checka a) (checkb b)'. It doesn't really matter what order 'a' and 'b' are checked, what I really want is the monad-style magic plumbing. I suppose I should just wrap 'process' in a liftM2 and stop worrying about it. Of course you must make sure you don't write more than one constructor function for ValidInt. This suggests a Can't you do this at the module level by exporting the ValidInt type, but not the constructor? Of course, then you have to stick it in its own module, and simple range validation is getting even more heavyweight... In response to the mysterious head exceptions thread, isn't there a way to compile with profiling and then get the rts to give a traceback on exception? ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
At 15:28 03/08/04 +0100, MR K P SCHUPKE wrote: f (case xs of (x:_) - x; [] - error whoops) -- direct style Yup, this is how I do it... I never use head! As a general principle, this bothers me. In the longer term (i.e. if and when large-scale production Haskell systems become common), and as a matter of principle, I think it's better to use a prelude (or standard) function when one will do the job, because a widely-used industrial strength compiler might well have special knowledge of these and be able to apply special optimizations (as, e.g., some C/C++ compilers do for standard library functions like memcpy). As for head, I think it's fine that it throws an error because it is specified to be defined for only non-empty lists. (I remain silent on whether the prelude should contain a head-like function that returns a value for empty lists.) #g Graham Klyne For email: http://www.ninebynine.org/#Contact ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
MR K P SCHUPKE [EMAIL PROTECTED] writes: head :: [a] - Maybe a head (a0:_) = Just a0 head _ = Nothing Argh, no! Violating the precondition of head is a bug in the caller, I want it to crash, but I also want to know where. Wrapping it up in Maybe (or any other error propagation) is not a solution. I don't want to write a lot of unwrapping code in all the callers, just to get a trackable error message in the (few) cases where I'm using the function incorrectly. Neither do I want to write (\x - if null x then error (__FILE__:__LINE__) else head x) everywhere instead of head, nor pollute my code with error tracking, but otherwise meaningless strings. (Which is what I generally do when I get this kind of anonymous error. if null x then error foo else head x. A mechanism for a function to report the caller site would obliviate the need for all this ugliness. -kzm Hmm...if I run it through CPP and #define HEAD (\x - if null x then error (__FILE__:__LINE__) else head x) is the __LINE__ resolved at the place of declaration or at the place of usage? -- If I haven't seen further, it is by standing in the footprints of giants ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
On 03-Aug-2004, Evan LaForge [EMAIL PROTECTED] wrote: In response to the mysterious head exceptions thread, isn't there a way to compile with profiling and then get the rts to give a traceback on exception? There is, but it doesn't really work properly, due to - lazy evaluation - tail call optimization - lack of line numbers in the traceback -- Fergus J. Henderson | I have always known that the pursuit Galois Connections, Inc.| of excellence is a lethal habit Phone: +1 503 626 6616 | -- the last words of T. S. Garp. ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] exceptions vs. Either
David Menendez writes: MR K P SCHUPKE writes: I would suggest using the type system as I said earlier so: toNonEmptyList :: [a] - Maybe (NonEmpty a) toNonEmptyList (a0:_) = Just (NonEmpty a) toNonEmptyList _ = Nothing Then redefine head: head :: NonEmpty a - a head (NonEmpty (a0:_)) = a0 Oleg described a similar technique a few months ago. From http://haskell.org/pipermail/haskell/2004-June/014271.html: | newtype NonEmpty a = NonEmpty [a] -- the NonEmpty constructor should | -- be hidden (not exported from its module) | | head' (NonEmpty a) = head a -- no error can occur! Can use unsafe version | tail' (NonEmpty a) = tail a -- no error can occur! Can use unsafe version | | -- trusted function: the only one that can use NonEmpty constructor. | fork_list_len f g x = if null x then f else g (NonEmpty x) | | revers x = revers' x [] | where |revers' x accum = fork_list_len accum (g accum) x |g accum x = revers' (tail' x) ((head' x):accum) We have these equivalences: toNonEmptyList== fork_list_len Nothing Just fork_list_len d f == maybe d f . toNonEmptyList I think defining 'toNonEmptyList' in terms of 'fork_list_len' is cleaner, but that's just my personal taste. (As it happens, I ended up defining a very similar function 'cons' in my recursion module[1]). [1] http://www.eyrie.org/~zednenem/2004/hsce/Control.Recursion.html#v% 3Acons -- David Menendez [EMAIL PROTECTED] http://www.eyrie.org/~zednenem/ ___ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe