[MLton-devel] phantom types and directed graphs

Stephen Weeks MLton@mlton.org
Tue, 11 Feb 2003 11:51:14 -0800


One problem with the approach I sent earlier is that requires the user
of the Graph module to define the new types and impose the
constraints.  That makes user code messier.  Another approach is to
force the type changes in the graph transform, as follows.

------------------------------------------------------------
signature DIRECTED_GRAPH_PHANTOM = 
   sig
      structure Node: 
	 sig
	    type 'a t
	 end
      
      type 'a t
      type 'a u (* unary notation for number of transforms *)

      val new: unit -> unit t
      val newNode: 'a t -> 'a Node.t
      val nodes: 'a t -> 'a Node.t list
      val transpose: 'a t -> 'a u t * {destroy: unit -> unit,
				       newNode: 'a Node.t -> 'a u Node.t}
   end
------------------------------------------------------------

I prefer this approach even though it has the drawback of confusing
graphs that have been through the same number of transformations.  It
would be possible to combine the approaches and use type ('a, 'b) t,
but that seems too messy to me.

I was a bit worried that all this polymorphism would cause MLton to
duplicate the graph code for every phantom type, but I now see that it
is possible to avoid that.  Here is a signature for non-phantom
graphs, as we have now, along with a functor that transforms them to
phantom graphs.  This shows that everything is happening at the type
level, on top of a monomorphic implementation.

------------------------------------------------------------
signature DIRECTED_GRAPH = 
   sig
      structure Node: 
	 sig
	    type t
	 end
      
      type t

      val new: unit -> t
      val newNode: t -> Node.t
      val nodes: t -> Node.t list
      val transpose: t -> t * {destroy: unit -> unit,
			       newNode: Node.t -> Node.t}
   end

functor Phantom (G: DIRECTED_GRAPH): DIRECTED_GRAPH_PHANTOM =
   struct
      open G
      structure Node =
	 struct
	    open Node
	    type 'a t = t
	 end
      
      type 'a t = t
      type 'a u = unit
   end
------------------------------------------------------------

Unfortunately, the above functor fails to type check in SML/NJ due to
an SML/NJ bug (#1548, which I reported on Feb 9, 2000!).  It does type
check with the other SML implementations.

Fortunately, directly instantiating the functor, as I will do for our
graphs, does type check under SML/NJ.

In trying to understand the SML/NJ bug, I noticed that the following
fails.

------------------------------------------------------------
functor F (S: sig
		 type t
		 val x: t
	      end):
   sig
      type 'a u
      val x: 'a u
   end =
   struct
      open S
      type 'a u = t
   end
------------------------------------------------------------

while the following, directly instantiating F, works

------------------------------------------------------------
structure S =
   struct
      type t = unit
      val x: t = ()
   end

structure F: 
   sig
      type 'a u
      val x: 'a u
   end =
   struct
      open S
      type 'a u = t
   end
------------------------------------------------------------

but the following, adding a signature constraint on S, fails

------------------------------------------------------------
structure S:
   sig
      type t
      val x: t
   end =
   struct
      type t = unit
      val x: t = ()
   end

structure F: 
   sig
      type 'a u
      val x: 'a u
   end =
   struct
      open S
      type 'a u = t
   end
------------------------------------------------------------

Go figure.


-------------------------------------------------------
This SF.NET email is sponsored by:
SourceForge Enterprise Edition + IBM + LinuxWorld = Something 2 See!
http://www.vasoftware.com
_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel