[Haskell-cafe] Why were unfailable patterns removed and "fail" added to Monad?
Michael Snoyman
michael at snoyman.com
Fri Jan 20 05:52:10 CET 2012
On Fri, Jan 20, 2012 at 6:41 AM, Edward Z. Yang <ezyang at mit.edu> wrote:
> Aw, that is really suboptimal. Have you filed a bug?
I think it's a feature, not a bug. When dealing with monads that
provide nice[1] implementations of `fail`, you can (ab)use this to
avoid writing a bunch of case expressions. I remember reading it in
one of the first tutorials on Haskell I looked at (four years ago now?
you can see how much this bothered me if I still remember that).
I admit that there are some use cases where the current behavior is
convenient, but I think we're paying too steep a price. If we got rid
of this feature entirely, we could (a) get rid of fail and (b) have
the compiler warn us about a bunch of errors at compile time.
But maybe I should file a feature request: provide an extra warning
flag (turned on by -Wall) that will warn when you match on a failable
pattern. Essentially, I would want:
SomeConstr args <- someAction
to be interpreted as:
temp <- someAction
case temp of
SomeConstr args ->
Michael
[1] For some people's definition of nice, not mine.
>
> Edward
>
> Excerpts from Michael Snoyman's message of Thu Jan 19 23:29:59 -0500 2012:
>> On Fri, Jan 20, 2012 at 5:23 AM, Edward Z. Yang <ezyang at mit.edu> wrote:
>> > Oh, I'm sorry! On a closer reading of your message, you're asking not
>> > only asking why 'fail' was added to Monad, but why unfailable patterns
>> > were removed.
>> >
>> > Well, from the message linked:
>> >
>> > In Haskell 1.4 g would not be in MonadZero because (a,b) is unfailable
>> > (it can't fail to match). But the Haskell 1.4 story is unattractive becuase
>> > a) we have to introduce the (new) concept of unfailable
>> > b) if you add an extra constructor to a single-constructor type
>> > then pattern matches on the original constructor suddenly become
>> > failable
>> >
>> > (b) is a real killer: suppose that you want to add a new constructor and
>> > fix all of the places where you assumed there was only one constructor.
>> > The compiler needs to emit warnings in this case, and not silently transform
>> > these into failable patterns handled by MonadZero...
>>
>> But wait a second... this is exactly the situation we have today!
>> Suppose I write some code:
>>
>> data MyType = Foo
>>
>> test myType = do
>> Foo <- myType
>> return ()
>>
>> 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 has
>> actually been something that bothers me a lot. Whereas everywhere else
>> in my pattern matching code, the compiler can make sure I didn't make
>> some stupid mistake, in do-notation I can suddenly get a runtime
>> error.
>>
>> My opinion is we should either reinstate the MonadZero constraint, or
>> simply can failable pattern matches.
>>
>> Michael
More information about the Haskell-Cafe
mailing list