Re: Proposal: System.Environment.getEnv should return Maybe

From: Jon Fairbairn
Brandon Allbery
writes: On Wed, Feb 22, 2012 at 18:51, John Meacham
wrote: On Wed, Feb 22, 2012 at 3:05 PM, Evan Laforge
wrote: It's awkward and surprising how getEnv throws an exception when an env var is not set, since it's very common for env vars to be optional, and it's not convenient to catch exceptions in haskell (I have to look
For true IO exceptions, you should be using the Prelude.catch mechanism.
This still assumes that it's an exceptional condition that is being modeled. It is not; it is correctly modeled as a Maybe.
+1. And it?s always irritated me that read at EOF raises an exception. Files having ends is not exceptional! (This is partly addressed by iteratees, I imagine, but I haven?t found time to get my head round those yet.)
This irritates me too; I don't think that Haskell exceptions should be used for much of anything, exceptional condition or not. +1 for the proposal. Also, the unix-bytestring package (http://hackage.haskell.org/package/unix-bytestring) exposes IO functions that don't raise exceptions at EOF. John L.

On 2/23/12 7:18 AM, John Lato wrote:
From: Jon Fairbairn
Brandon Allbery writes: On Wed, Feb 22, 2012 at 18:51, John Meacham
wrote: On Wed, Feb 22, 2012 at 3:05 PM, Evan Laforge
wrote: It's awkward and surprising how getEnv throws an exception when an env var is not set, since it's very common for env vars to be optional, and it's not convenient to catch exceptions in haskell (I have to look
For true IO exceptions, you should be using the Prelude.catch mechanism.
This still assumes that it's an exceptional condition that is being modeled. It is not; it is correctly modeled as a Maybe.
+1. And it?s always irritated me that read at EOF raises an exception. Files having ends is not exceptional! (This is partly addressed by iteratees, I imagine, but I haven?t found time to get my head round those yet.)
This irritates me too; I don't think that Haskell exceptions should be used for much of anything, exceptional condition or not.
+1 for the proposal.
Also, the unix-bytestring package (http://hackage.haskell.org/package/unix-bytestring) exposes IO functions that don't raise exceptions at EOF.
+1 for having getEnv return Maybe instead of throwing an exception. -- Live well, ~wren

On 23 February 2012 20:18, John Lato
From: Jon Fairbairn
Brandon Allbery
writes: On Wed, Feb 22, 2012 at 18:51, John Meacham
wrote: On Wed, Feb 22, 2012 at 3:05 PM, Evan Laforge
wrote: It's awkward and surprising how getEnv throws an exception when an env var is not set, since it's very common for env vars to be optional, and it's not convenient to catch exceptions in haskell (I have to look
For true IO exceptions, you should be using the Prelude.catch mechanism.
This still assumes that it's an exceptional condition that is being modeled. It is not; it is correctly modeled as a Maybe.
+1. And it?s always irritated me that read at EOF raises an exception. Files having ends is not exceptional! (This is partly addressed by iteratees, I imagine, but I haven?t found time to get my head round those yet.)
This irritates me too; I don't think that Haskell exceptions should be used for much of anything, exceptional condition or not.
+1 to the general concept of not using Haskell exceptions in library code.
+1 for the proposal.
+1 Conrad.

On Fri, 24 Feb 2012, Conrad Parker wrote:
On 23 February 2012 20:18, John Lato
wrote: This irritates me too; I don't think that Haskell exceptions should be used for much of anything, exceptional condition or not.
+1 to the general concept of not using Haskell exceptions in library code.
This depends on what you call "exception". The exception handling part of the IO monad? The general concept of an exceptional situation? I think if you request the value of a variable, but that variable turns out to not exist, then the question was not valid and that is somehow an exceptional situation. Whether this should be handled by IO's exception handling mechanism or by another one is an interesting question. Whether a non-existent variable shall abort the control flow or not, is another one. I do not like the implicit nature of IO exceptions and thus wrote the package explicit-exception. It is Haskell 98 and provides an Either and an ErrorT like type with appropriate name and no 'fail' implementation, thus with unrestricted types of exceptions. In this approach the switch from an aborting getEnv to a non-aborting getEnv just consists of unwrapping the ExceptionalT monad transformer. Btw. the library also contains a suggestion of how to handle asynchronous exceptions, but unfortunately it suffers from a memory leak in practice (at least in GHC). http://hackage.haskell.org/package/explicit-exception

On Sun, Mar 11, 2012 at 14:12, Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Fri, 24 Feb 2012, Conrad Parker wrote:
On 23 February 2012 20:18, John Lato
wrote: This irritates me too; I don't think that Haskell exceptions should be used for much of anything, exceptional condition or not.
+1 to the general concept of not using Haskell exceptions in library code.
This depends on what you call "exception". The exception handling part of the IO monad? The general concept of an exceptional situation? I think if you request the value of a variable, but that variable turns out to not exist, then the question was not valid and that is somehow an exceptional situation.
Is looking up a missing key in a Map an exception? That is exactly this case ("variable" is really only an appropriate term from the standpoint of the shell, which [sometimes inappropriately] conflates the environment with its own variables). Or are you arguing that that also should be an exception? -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms

On Sun, 11 Mar 2012, Brandon Allbery wrote:
Is looking up a missing key in a Map an exception?
It is certainly an exceptional situation. You want to know the value that is associated with a key, but the answer is not the wanted value, but no value at all.
That is exactly this case ("variable" is really only an appropriate term from the standpoint of the shell, which [sometimes inappropriately] conflates the environment with its own variables). Or are you arguing that that also should be an exception?
"exception" in what sense? Certainly not an exception in IO, since I do not like the implicitness of exceptions in IO. No I think, Maybe is a perfect return type for 'lookup'. What I want to say is, that Nothing is also an exceptional value. A different question is, how to cope with that value. Abort a sequence of computations? This can be easily done in the Maybe monad and looks more like conventional exception handling. Do an alternative computation? This could be done using 'case' or 'maybe'. The good thing about Haskell is, that if exceptions would be consistently handled by types like Maybe, MaybeT, ExceptionalT etc. then we could really simply choose between different ways of coping with exceptional values.

On Sun, Mar 11, 2012 at 16:33, Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Sun, 11 Mar 2012, Brandon Allbery wrote:
Is looking up a missing key in a Map an exception?
It is certainly an exceptional situation. You want to know the value that is associated with a key, but the answer is not the wanted value, but no value at all.
So you will insist that lookup when the key doesn't exist throw an exception? If not, why not? If we're going to make interfacing with the system as difficult and minetrap-strewn as possible, then let's cut to the chase and switch to Agda. Or we need to change a bunch of IO (Maybe x) to throw approved exceptions and make them suitably difficult to use for our walled garden instead of thinking about whether that's appropriate. Or, just maybe, we just need to stop thinking of it's-in-IO-it-should-throw-an-exception-at-every-opportunity-instead-of-being-*usable*. IO's enough of a sewer as it is without turning it into don't-think-about-it-just-hork-a-hairball too.
"exception" in what sense? Certainly not an exception in IO, since I do not like the implicitness of exceptions in IO. No I think, Maybe is a perfect return type for 'lookup'. What I want to say is, that Nothing is also an exceptional value.
(So, you just tossed in

On Sun, 11 Mar 2012, Brandon Allbery wrote:
"exception" in what sense? Certainly not an exception in IO, since I do not like the implicitness of exceptions in IO. No I think, Maybe is a perfect return type for 'lookup'. What I want to say is, that Nothing is also an exceptional value.
(So, you just tossed in
C-style without looking at the context?)
You mean something like "Ceterum censeo Carthaginem esse delendam"? :-)
The context is that getEnv currently throws an IO exception if the name isn't found, and we'd like it to be IO (Maybe String) because it's really a keyed store where absence of the key isn't really justification for an IO exception, but is a reasonable use for a Maybe. It's the cranky IO exception that needs to go away, not the notion of an exceptional condition in general.
I replied to Conrad Parker who said "+1 to the general concept of not using Haskell exceptions in library code." and John Lato who said something similar. If they refer with "Haskell exceptions" to the exceptions that are implicit in the IO monad, then I support this proposal. That's the context I refered to. If no IO exceptions for getEnv then two main alternatives remain: IO (Maybe String) and MaybeT IO String (or ErrorT e IO String or ExceptionalT e IO String). The switch between these two is simple - simpler than the one between IO exception and IO Maybe. The choice between them should depend on what we expect to be the most frequent case: If aborting a series of computations is the main use case, then the type should be MaybeT IO String. If choosing an alternative action in case of getEnv returning Nothing is the main use case, then the type might be better IO (Maybe String). But even in this case you could use mzero on MaybeT IO String. Both use cases seem to be reasonable to me. So what is the main use case? Currently there is no one planning to use MaybeT in System.Environment, since this would mean to make base/haskell2010 depend on transformers. But an option might be to start a package where generally IO exceptions are replaced by MaybeT and its friends. Then we could leave System.Environment as it is.

On Mon, Mar 12, 2012 at 04:58, Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Sun, 11 Mar 2012, Brandon Allbery wrote:
The context is that getEnv currently throws an IO exception if the name isn't found, and we'd like it
to be IO (Maybe String) because it's really a keyed store where absence of
the key isn't really justification for an IO exception, but is a reasonable use for a Maybe. It's the cranky IO exception that needs to go away, not the notion of an exceptional condition in general.
I replied to Conrad Parker who said "+1 to the general concept of not using Haskell exceptions in library code." and John Lato who said something similar. If they refer with "Haskell exceptions" to the exceptions that are implicit in the IO monad, then I support this proposal. That's the context I refered to.
It was pretty clear to me, following form the start, that Control.Exception was meant. I will, however, note that while referring to out of band data as "exceptional" is in some sense pedantically correct, it also leads to precisely *this* confusion. Commonly an "exception" is understood as a form of non-local goto that propagates into a runtime abort if not handled appropriately, not simply an out of band datum indicating e.g. the absence of a value; bringing the pedantic definition into a random discussion, at least without establishing relevance, engenders confusion instead of reducing it.
Currently there is no one planning to use MaybeT in System.Environment, since this would mean to make base/haskell2010 depend on transformers. But an option might be to start a package where generally IO exceptions are replaced by MaybeT and its friends. Then we could leave System.Environment as it is.
Some things in IO are reasonably Control.Exception, and some things aren't. (Yay, sewer.) Although at least some things that are reasonably Control.Exception might lead to simplified code in some use cases if expressed with MaybeT, this must be done carefully as many things are not safely characterized as such; in particular, I'm wondering if having handle-close return an out of band failure instead of a Control.Exception implies a causal relationship that may not exist (as the close() may be indicating that a prior write() failed — not that the close() itself failed — in particular with sockets). -- brandon s allbery allbery.b@gmail.com wandering unix systems administrator (available) (412) 475-9364 vm/sms
participants (5)
-
Brandon Allbery
-
Conrad Parker
-
Henning Thielemann
-
John Lato
-
wren ng thornton