> No exceptions
> Exceptions are also a side effect handled by the type
> system. We know our function is pure and won’t throw
> an exception.
> The input can either be true or false. Once you have
> tested the result of these two possibilities, you
> have the holy grail. No exceptions, no infinite
> loops, no incorrect results, no errors.
You're right about the bottom input. I'll add it to the article.
Prelude> head 
*** Exception: Prelude.head: empty list
Either way, pure code can throw exceptions in Haskell. Consider division by zero for example.
Prelude> :t error
error :: [Char] -> a
Prelude> :t undefined
undefined :: t
Prelude> :t assert
assert :: Bool -> a -> a
Prelude Control.Exception> :t throw
throw :: Exception e => e -> a
I wasn't aware of 'throw' and that certainly weakens my argument. You could maybe argue it is an escape hatch in the same vein as unsafePerformIO, but I don't know how it is viewed by the community.
You could argue I'm playing word games here, and I have some sympathy for that argument. What I wanted to get across is checked exceptions ala. Java (although they are too commonly bypassed in that example). Maybe moving it to the documentation section is a good compromise.
Okay, but in the case of GHC you actually can recover from them.
> I wasn't aware of 'throw' and that certainly weakens my argument. You could maybe argue it is an escape hatch in the same vein as unsafePerformIO, but I don't know how it is viewed by the community.
Asynchronous exceptions are pretty widely accepted as the way to interrupt a long-running pure computation. `error` is pretty widely used on identifying programming errors and pretty well reserved to that case. There is some dispute over whether exceptions or Either is more appropriate to dealing with exceptional conditions in IO; more reluctance around exceptions for reporting exceptional conditions outside of IO (partly because of the "only catch in IO" restriction, and substantially because we have other, good methods).
> What I wanted to get across is checked exceptions ala. Java (although they are too commonly bypassed in that example).
I'd like to see some language flesh out checked exceptions with parametric polymorphism. Alack, this is not what Haskell has (yet?) done.
For synchronous exceptions Haskell is sort of middle-of-the-road, differing from other languages mostly in providing other options that are substantially better for many use cases.