[MLton] sequenceNonUnit

Matthew Fluet fluet@cs.cornell.edu
Fri, 5 Aug 2005 21:13:48 -0400 (EDT)


> > Thinking about it briefly, I came up with the following
> > implementation scheme. During the recursive type inference step, the
> > inferred type (which may be a variable) of the "ignored expression"
> > is saved to a list (along with the necessary info to give proper
> > diagnostics). After type inference, a diagnostic would be given for
> > each non-unit type in the list. This way the diagnostic given for
> > the latentError example above, and other similar cases, would
> > (properly) point to the "ignored expression".
> >
> > Would this work and capture the intention of sequenceNonUnit?
> 
> Yes.  It looks good.

I did a simple implementation of this, and I think it works fairly well.  
However, it does print an error/warning for sequence expressions with 
non-unit types that are later constrained by a signature to be unit.  For 
example, from the Basis Library implementation:

Warning: <basis>/misc/dynamic-wind.sml 16.25.
  Sequence expression not of type unit.
    type: ['a]
    in: cleanup ()
Warning: <basis>/misc/dynamic-wind.sml 16.50.
  Sequence expression not of type unit.
    type: ['a]
    in: cleanup ()

where the Basis Library implementation has:

signature DYNAMIC_WIND =
   sig
      val wind: (unit -> 'a) * (unit -> unit) -> 'a
   end
structure DynamicWind: DYNAMIC_WIND =
struct

fun try (f: unit -> 'a, k: 'a -> 'b, h: exn -> 'b) =
   let
      datatype t =
	 A of 'a
       | E of exn
   in
      case A (f ()) handle e => E e of
	 A a => k a
       | E e => h e
   end
	 
fun wind (thunk, cleanup) =
   try (thunk, fn a => (cleanup (); a), fn e => (cleanup (); raise e))

end

To fix the warning, you need to put a type annotation on cleanup.  I think
this behavior is fine, because it would be fairly difficult (I believe) to
distinguish the above case from one where wind was also used within the
structure at non-unit type.