[MLton] cvs commit: major improvements to -show-basis

Stephen Weeks MLton@mlton.org
Thu, 12 Feb 2004 14:32:44 -0800


> Abstract types in signatures are displayed as type equalities:
> 
>   signature ARRAY2 =
>      sig
>         type 'a array = 'a array
>         ...
>      end
> 
> I'm confused by the "= 'a array"; it seems to suggest a type equality with
> the top-level array, but that is clearly incorrect. 

Yeah.  It is supposed to indicate that type name array denotes the
flexible tycon (local to this signature) called array.  The problem
that I had was how to uniquely identify tycons when displaying
signatures.  I decided it was too hard to try to generate valid
sigexps.  Consider the following signature

signature S =
   sig
      type t
      structure U:
	 sig
	    val x: t
	    type t
	    val y: t
	 end
   end

By the time this has been elaborated, MLton has long lost the
information about how the specs were ordered, and I thought it would
be confusing/difficult to try to figure out some clever order on the
specs.  The problem with the above signature is that I want to
distinguish between the type of x and y despite the fact that they
appear next to each other.  I decided it would be best to display
signatures in a "canonical" form, where all types are shown, then all
value specs, and then all structure specs, with each of the three
components alphabetized by name.  The types in value specs should also
be canonical.  This is done by choosing a unique name for each
flexible tycon in the signature.  That unique name is (or will be
soon) chosen to be the shortest longtycon that denotes the flexible
tycon in the signature.  So, type t in signature S will be shown as
"t" and type t defined in the U strcuture spec will be shown as "U.t".
Thus, the signature is displayed as

signature S =
   sig
      type t = t
      structure U:
         sig
            type t = U.t
            val x: t
            val y: U.t
         end
   end

I can see that this is confusing, since the usual scoping rules for
signatures mean that "type t = t" is defining type t to be the "t"
that is defined at some outer scope.

The best fix that I can think of is to choose some prefix that
distinguishes all the flexible tycons in the signature.  Offhand, the
best prefix I can think of is "?." (intuitively, we don't know what
structure binds the tycon).  That would make the above signature
display as

signature S =
   sig
      type t = ?.t
      structure U:
         sig
            type t = ?.U.t
            val x: ?.t
            val y: ?.U.t
         end
   end

This at least makes it clear when a tycon in a signature is flexible
or not, and I think makes things completely unambiguous.

I've checked in this change.  Have a look at the basis and let me know
what you think.

> "Bad defaults" for equivalent types:
> 
> signature BIN_IO =
>    sig
>       type elem = BinIO.elem


My recent checkin fixes this.  We now see

signature BIN_IO = 
   sig
      type elem = Word8.word
...

> Implementation type of Socket.SOCK.sock_type is exposed:
> signature GENERIC_SOCK =
>    sig
>       val socket: (NetHostDB.addr_family * int) -> ('a, 'b) Socket.sock
>       val socket': (NetHostDB.addr_family * int * int)
>                    -> ('a, 'b) Socket.sock
>       val socketPair: (NetHostDB.addr_family * int)
>                       -> (('a, 'b) Socket.sock * ('a, 'b) Socket.sock)
>       val socketPair': (NetHostDB.addr_family * int * int)
>                        -> (('a, 'b) Socket.sock * ('a, 'b) Socket.sock)
>    end
> The first int in each tuple should be the (abstract)
> Socket.SOCK.sock_type.

Fixed.  We now see

signature GENERIC_SOCK = 
   sig
      val socket: (NetHostDB.addr_family * Socket.SOCK.sock_type)
		  -> ('a, 'b) Socket.sock
      val socket': (NetHostDB.addr_family * Socket.SOCK.sock_type * int)
		   -> ('a, 'b) Socket.sock
      val socketPair: (NetHostDB.addr_family * Socket.SOCK.sock_type)
		      -> (('a, 'b) Socket.sock * ('a, 'b) Socket.sock)
      val socketPair': (NetHostDB.addr_family * Socket.SOCK.sock_type * int)
		       -> (('a, 'b) Socket.sock * ('a, 'b) Socket.sock)
   end