I would rather tell someone that to define a new type exactly
  isomorphic to an old type they need to write
        newtype  Type = Constructor typeexp
  then tell them that they need to write
        data  Type = Constructor !typeexp
  The latter smacks too much of magic.  This is clearly a matter of
  taste, where reasonable people may disagree; I'm just putting forward
  my preference.
  

Actually I agree, but I'd like the more general capability as well.
We then just need to decide whether the syntax above is justifiable
shorthand for that special situation.

  Paul's suggestion that ! annotations in the type should change the
  meaning of a value worries me.  It is bound to make reasoning more
  difficult.  Paul, do you have a formal specification of how the type
  annotations should affect the semantics?
  

I would propose first that the ! annotation can only be applied at
the outermost level (i.e. a -> !b -> c is OK, a -> (a->!b) -> c is
not OK).  I presume that LML places a similar constraint on data
constructor annotations.

Equationally the rest seems obvious; if a function f has type 

t1 -> !t2 -> t3, its semantics is modified so that:

  f x _|_ y = _|_
  

I think it's straightforward to express this as an "expansion" of
f's definition in terms of "strict".
  

  It would be more in the
  spirit of Haskell to require annotations in the function definition,
  from which the annotations in the type can be inferred.

Yeah, this would be OK; it is a matter of taste.  One could do:

  f x !y z = ...
  

(I should also point out an elegant, but otherwise horrible solution:
have variables DEFAULT to being strict, and require a ~ if you want
one to be lazy -- this eliminates the need for ! altogether, and
actually makes the use of ~ more consistent, but of course it will
cause most programs to have 10 gazillion ~'s (!) :-)

  -Paul

Reply via email to