I don't like Phil's suggestion to have non-lifted products:
* It messes up the uniform semantics for algebraic data types (all lifted).
For example
a) You have to explain that
f ~(z,a) = ... is the same as f (z,a) = ...
but
g ~(z:a) = ... is NOT the same as f (z:a) = ...
b) You have to explain that if
f (Foo y) = ...
then f is strict if Foo is one of a multi-constructor data type, but
non-strict otherwise (unless "..." is strict in y!)
(Unless non-lifted products are a different construct, which complicates
the language, and
* An alternative is, I suppose, to have both standard, lifted algebraic data
types, and a new form of data construction, namely non-lifted tuples. I like it
not!
* Lennart says that if the non-lifted products can also have strictness
annotations then it requires parallel evaluation. I think it's rather
amazing that one can implement non-lifted products without parallelism; doing
so in the presence of strictness annoations makes my head hurt. I bet
Lennart is right.
Efficiency was not the only reason for having lifted tuples; semantic uniformity
was a major one.
Incidentally, a much less invasive way to achieve what Phil wants
would be to say that there's a ~ stuck on every pattern from a
single-constructor data type (or built-in tuple type?). Myself, I'd dislike
this, esp if there was no way to "undo" it and recover strict matching, but it
solves Phil's problem without adding new data types.
Simon