Phil writes:


| 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!

I believe it would be a mistake to do this!  Consider:

        newtype Age = Age Int
        
        foo :: Age -> (Int, Age)
        foo (Age n) = (n, Age (n+1))

Now, we intend that a value of type (Age Int) should be represented by
an Int.  Thus, apart from the types involved, the following program should
be equivalent:

        type Age' = Int

        foo' :: Age' -> (Int, Age')
        foo' n = (n, n+1)

So is foo' strict in n? No, it isn't.  What about foo?  If newtype is just a
strict data constructor, then it *is* strict in n.

Here's what I wrote a little while ago:

"This all very well, but it needs a more formal treatment.  As it happens, I
don't think it's difficult.  In the rules for case expressions (Fig 3 & 4 in
the 1.2 report) we need to say that the *dynamic* semantics of

        case e of { K v -> e1; _ -> e2 }
is
        let v = e in e1

if K is the constructor of a "newtype" declaration.
(Of course this translation breaks the static semantics.)

Similarly, the dynamic semantics of (K e) is just that of "e", if
K is the constructor of a "newtype" decl."

Does that make the semantics clear, Phil?

Simon



Reply via email to