The design of newtype appears to me incorrect.
The WWW page says that declaring
newtype Foo = Foo Int
is distinct from declaring
data Foo = Foo !Int
(where ! is a strictness annotation) because the former gives
case Foo undefined of Foo _ -> True = True
and the latter gives
case Foo undefined of Foo _ -> True = undefined.
Now, on the face of it, the former behaviour may seem preferable. But
trying to write a denotational semantics is a good way to get at the
heart of the matter, and the only way I can see to give a denotational
semantics to the former is to make `newtype' define a LIFTED type, and
then to use irrefutable pattern matching. This seems positively weird,
because the whole point of `newtype' is that it should be the SAME as
the underlying type.
By the way, with `newtype', what is the intended meaning of
case undefined of Foo _ -> True ?
I cannot tell from the summary on the WWW page. Defining `newtype'
in terms of `datatype' and strictness avoids any ambiguity here.
Make newtype equivalent to a datatype with one strict constructor.
Smaller language, more equivalences, simpler semantics, simpler
implementation. An all around win!
Cheers, -- P