[Haskell-cafe] Use unsafePerformIO to catch Exception?

wren ng thornton wren at freegeek.org
Thu Mar 26 20:23:04 EDT 2009


Jules Bean wrote:
> wren ng thornton wrote:
> > I have long been disappointed by a number of `error`s which shouldn't 
> > be. For example, the fact that `head` and `div` are not total strikes 
> > me as a (solvable) weakness of type checking, rather than things that 
> > should occur as programmer errors/exceptions at runtime. The use of 
> > `error` in these cases muddies the waters and leads to a laissez-faire 
> > attitude about when it's acceptable to throw one's hands up in despair 
> > and use `error` rather than writing a better function.
> 
> head uses "error" in precisely the correct, intended fashion.
> 
> head has a precondition (only call on non-empty lists)

And that is *exactly* my complaint: the precondition is not verified by 
the compiler. Therefore it does not exist in the semantic system, which 
is why the error screws up semantic analysis.

The type of head should not be [a] -> a + Error, it should be (a:[a]) -> 
a. With the latter type the compiler can ensure the precondition will be 
proved before calling head, thus eliminating erroneous calls.

It's a static error, detectable statically, and yet it's deferred to the 
runtime. I'd much rather the compiler catch my errors than needing to 
create an extensive debugging suite and running it after compilation. Is 
this not the promise of purity?


> There are programming styles which avoid using 'head'. You are free to 
> use those if you don't like it. I myself am content to use 'head' on 
> lists which I know are guaranteed to be non-empty.

Avoiding head is not a tenable solution. The syntax for case matching is 
insufficiently first-class, so avoiding the function often leads to 
contortions, illegible code, or reinventing the problem. Moreover, this 
isn't an isolated case; fromJust is another canonical example, as is any 
other partial algebra-homomorphism. Many mathematical functions like div 
are also subject to trivially-verified invariants on their arguments.

Functions like uncons and viewL are nicer (because they're safe), but 
they can have overhead because they're unnecessarily complete (e.g. the 
Maybe wrapper can be avoided if we know a-priori that Just will be the 
constructor used).

-- 
Live well,
~wren


More information about the Haskell-Cafe mailing list