[Haskell-cafe] Re: Pattern matching, and bugs
jwlato at gmail.com
Fri Dec 18 09:13:02 EST 2009
> Date: Fri, 18 Dec 2009 13:04:47 +0100
> From: Andr?s Mocs?ry <amocsy at gmail.com>
> switch 1 = "Unchecked"
> switch 2 = "Checked"
> switch 3 = "Unknown"
> switch x = "Nothing"
> These general ways really avoid this particular crash, but does something
> real bad to the code in my opinion.
> Which leads to the very reason I wrote to you:
> I want to propose this for Haskell prime:
> I would like to have a way for Haskell, not to crash, when my coders write
> pattern matching without the above mentioned general case.
I will first make a recommendation, then some comments on your proposal.
My recommendation is this: if you know that a function should only be
called with certain values, you should create a data type that has
*only* those values, like:
data ForSwitch = One | Two | Three
then your switch function is
switch :: ForSwitch -> String
and now it can be guaranteed *at compile-time* that switch will never
be called with an incorrect argument, because only arguments are
available in the ForSwitch type and they're all valid. It's now
impossible for another part of the program to generate invalid data.
It either generates a ForSwitch, which is guaranteed to be valid, or
it doesn't, in which case the code won't typecheck.
Note that if you really just want to wrap Int's, you can use a newtype
and a smart constructor, which if written correctly gives you the same
guarantees but is in my mind less convenient.
Now, as for a general response to your proposal, I'm not sure that
what you're requesting is possible, and I'm quite certain it would be
more trouble than it's worth.
> Like having the compiler auto-include those general cases for us,
> but when those cases got hit, then* instead of crashing*, it *should **report
> some error* on *stdout *or *stderr*.
> (It would be even nicer if it cold have been traced.)
What should the program do after reporting an error?
Because of Haskell's non-strict evaluation, a function is only
evaluated when your program *needs the result*. The compiler can't
infer a meaningful value for an arbitrary type, and the only value
that can be in every type is undefined. So now the program needs a
result of some type (String in your example) and gets an undefined,
and then immediately crashes with an "Exception - undefined" error.
As for network-corrupted data, the solution is the same. Make a type
that reflects *only* the values you want. Then it's the
responsibility of the serializer/deserializer to ensure that you have
a correct value, using explicit error handling (Maybe or Either come
to mind). Then you know that all data in your system is valid, and
you only need to worry about invalid data at borders, where the
problem is much easier to address.
More information about the Haskell-Cafe