Re: [Haskell-cafe] Why were unfailable patterns removed and "fail" added to Monad?

On Jan 20, 2012 8:31 AM, "John Meacham"
As expected, no warnings. But if I change this "unfailable" code above to the following failable version:
data MyType = Foo | Bar
test myType = do Foo <- myType return ()
I *still* get no warnings! We didn't make sure the compiler spits out warnings. Instead, we guaranteed that it *never* will.
This is actually the right useful behavior. using things like
do Just x <- xs Just y <- ys return (x,y)
will do the right thing, failing if xs or ysresults in Nothing. for instance, in the list monad, it will create the cross product of the non Nothing members of the two lists. a parse monad may backtrack and try another route, the IO monad will create a useful (and deterministic/catchable) exception pointing to the exact file and line number of the pattern match. The do notation is the only place in haskell that allows us to hook into the pattern matching mechanism of the language in a general way.
John
I mention later that this is a "feature, not a bug" to some people, but I'm not one of them. The convenience of having this feature is IMO far outweighed by the cost of the runtime errors it can produce if you use the pattern matching in the wrong monad (e.g., IO, Reader, Writer...). Michael

On Jan 20, 2012, at 1:40 AM, Michael Snoyman wrote:
On Jan 20, 2012 8:31 AM, "John Meacham"
wrote: As expected, no warnings. But if I change this "unfailable" code above to the following failable version:
data MyType = Foo | Bar
test myType = do Foo <- myType return ()
I *still* get no warnings! We didn't make sure the compiler spits out warnings. Instead, we guaranteed that it *never* will.
This is actually the right useful behavior. using things like
do Just x <- xs Just y <- ys return (x,y)
will do the right thing, failing if xs or ysresults in Nothing. for instance, in the list monad, it will create the cross product of the non Nothing members of the two lists. a parse monad may backtrack and try another route, the IO monad will create a useful (and deterministic/catchable) exception pointing to the exact file and line number of the pattern match. The do notation is the only place in haskell that allows us to hook into the pattern matching mechanism of the language in a general way.
John
I mention later that this is a "feature, not a bug" to some people, but I'm not one of them. The convenience of having this feature is IMO far outweighed by the cost of the runtime errors it can produce if you use the pattern matching in the wrong monad (e.g., IO, Reader, Writer...).
It seems like there must be deeper reasons than stated so far for wanting to remove the "failable" concept from the spec, because all the ones given so far seem more like pros than cons. For example, those runtime errors would be type errors! And when adding additional constructors to a single-constructor type, it would not silently change the meaning in most places - it would cause type errors in places where the binding no longer makes sense and "change the meaning" in a predictable way (the way it does now) in places where it does make sense. The former sounds fantastic to me, and the latter sounds acceptable (but a warning for those who don't find it acceptable would be a good idea too). There is of course still a risk that adding a constructor can cause silent misbehavior in code that uses those type of bindings in monads that _are_ instances of MonadZero, but personally the number of times I have been bitten by that or heard of anyone else actually being bitten by it (i.e., zero) is a lot smaller than the number of times I've decided a "failable" binding was just the right concise-and-clear way to implement a parser, filter, etc. The only problem I have with that style is the fact that it is not rejected in places where it doesn't make sense. -- James
participants (2)
-
James Cook
-
Michael Snoyman