[MLton-devel] Possible type-inference bug

Jesper Louis Andersen jlouis@mongers.org
Tue, 14 Oct 2003 01:29:47 +0200


First, I do not know if this is a bug in the type-inference pass,
but what I have here is being checked without problems by SML/NJ 
110.42 but not by mlton. I did not completely understand the known
bug, so there is a caveat that I might have hit exactly that (read:
I have not yet dug into that bug and why it is a bug and the SML
code example in question).

First the MLton version:

(MLton MLTONVERSION (built Mon Oct 13 01:22:54 2003 on sarah))

What is the code in question? It is a little Xhtml library I've toyed
with. The idea is that XML can be represented by four operations:

concatenation (op+++): xt +++ xt'; xt,xt' is XML trees, will yield
	a new XML tree which is the concatenation of these 2

injection (op<<<): tag <<< xt; xt is XML tree, tag is a XML tag
	will yield the XML tree where xt is injected inside tag, eg
	<tag>xt</tag>.

pure strings (op$): $ str yields the string str

augmentation(op!): t ! (pl), will augment the tag with parameters 
	in the parameter list pl, eg:
	(A ! ("href", "http://www.mlton.org")) <<< ($ "mlton.org")
	yields:
	<a href="http://www.mlton.org">mlton.org</a>

Thus we now have a nice little combinator library for producing
XML, so we build an Xhtml structure from it, pulling the relevant
information out. But of course there is a flatten function which
takes an XML tree to a string. Performance has not been into
consideration yet in this. It is the place where I expect the
MLton profiler to be able to do wonders. 

Anyway, here is what happens in MLton:

Error: Xhtml.sml 155.1: unable to infer type for HEAD
   type: string * ??? list
   dec: val HEAD = X.buildTag ("head", [])
Error: Xhtml.sml 156.1: unable to infer type for TITLE
   type: string * ??? list
   dec: val TITLE = X.buildTag ("title", [])
Error: Xhtml.sml 157.1: unable to infer type for BODY
   type: string * ??? list
   dec: val BODY = X.buildTag ("body", [])
Error: Xhtml.sml 158.1: unable to infer type for H1
   type: string * ??? list
   dec: val H1 = X.buildTag ("h1", [])
Error: Xhtml.sml 159.1: unable to infer type for H2
   type: string * ??? list
   dec: val H2 = X.buildTag ("h2", [])
Error: Xhtml.sml 160.1: unable to infer type for H3
   type: string * ??? list
   dec: val H3 = X.buildTag ("h3", [])
Error: Xhtml.sml 161.1: unable to infer type for H4
   type: string * ??? list
   dec: val H4 = X.buildTag ("h4", [])
Error: Xhtml.sml 162.1: unable to infer type for H6
   type: string * ??? list
   dec: val H6 = X.buildTag ("h6", [])
Error: Xhtml.sml 163.1: unable to infer type for P
   type: string * ??? list
   dec: val P = X.buildTag ("p", [])
Error: Xhtml.sml 164.1: unable to infer type for ADDRESS
   type: string * ??? list
   dec: val ADDRESS = X.buildTag ("address", [])
compilation aborted: elaborate reported errors

---------------------------------------------------------------
But for SML/NJ 110.42:

jlouis@sarah$ sml Xhtml.sml
Standard ML of New Jersey v110.42 [FLINT v1.5], October 16, 2002
[opening Xhtml.sml]
[autoloading]
[autoloading done]
signature XML =
  sig
    type parameter
    type tag
    datatype xmltree
      = Concat of xmltree * xmltree
      | Inject of tag * xmltree
      | Str of string
      | Tag of tag
    val augment : tag * parameter list -> tag
    val buildString : string -> xmltree
    val buildTag : string * (string * string) list -> tag
    val flatten : xmltree -> string
  end
structure Xml : XML
signature XML_STRUCTS =
  sig
    structure Xml :
      sig
        type parameter
        type tag
        datatype xmltree
          = Concat of xmltree * xmltree
          | Inject of tag * xmltree
          | Str of string
          | Tag of tag
        val augment : tag * parameter list -> tag
        val buildString : string -> xmltree
        val buildTag : string * (string * string) list -> tag
        val flatten : xmltree -> string
      end
  end
signature XML_COMBINATORS =
  sig
    structure Xml :
      sig
        type parameter
        type tag
        datatype xmltree
          = Concat of xmltree * xmltree
          | Inject of tag * xmltree
          | Str of string
          | Tag of tag
        val augment : tag * parameter list -> tag
        val buildString : string -> xmltree
        val buildTag : string * (string * string) list -> tag
        val flatten : xmltree -> string
      end
    val +++ : Xml.xmltree * Xml.xmltree -> Xml.xmltree
    val <<< : Xml.tag * Xml.xmltree -> Xml.xmltree
    val ! : Xml.tag * Xml.parameter list -> Xml.tag
    val $ : string -> Xml.xmltree
  end
functor XmlCombinators(<param>: sig structure Xml : <sig> end) :
                      sig
                        structure Xml : <sig>
                        val +++ : Xml.xmltree * Xml.xmltree -> Xml.xmltree
                        val <<< : Xml.tag * Xml.xmltree -> Xml.xmltree
                        val ! : Xml.tag * Xml.parameter list -> Xml.tag
                        val $ : string -> Xml.xmltree
                      end
signature XHTML_STRUCTS =
  sig
    structure X :
      sig
        type parameter
        type tag
        datatype xmltree
          = Concat of xmltree * xmltree
          | Inject of tag * xmltree
          | Str of string
          | Tag of tag
        val augment : tag * parameter list -> tag
        val buildString : string -> xmltree
        val buildTag : string * (string * string) list -> tag
        val flatten : xmltree -> string
      end
  end
signature XHTML =
  sig
    structure X :
      sig
        type parameter
        type tag
        datatype xmltree
          = Concat of xmltree * xmltree
          | Inject of tag * xmltree
          | Str of string
          | Tag of tag
        val augment : tag * parameter list -> tag
        val buildString : string -> xmltree
        val buildTag : string * (string * string) list -> tag
        val flatten : xmltree -> string
      end
    val XHTML_Header : string
    val HTML : X.tag
    val HEAD : X.tag
    val TITLE : X.tag
    val BODY : X.tag
    val H1 : X.tag
    val H2 : X.tag
    val H3 : X.tag
    val H4 : X.tag
    val H6 : X.tag
    val P : X.tag
    val ADDRESS : X.tag
    val buildRef : string -> X.tag
    val comment : string -> string
    val +++ : X.xmltree * X.xmltree -> X.xmltree
    val <<< : X.tag * X.xmltree -> X.xmltree
    val ! : X.tag * X.parameter list -> X.tag
    val $ : string -> X.xmltree
  end
functor Xhtml(<param>: sig structure XmlCombinators : <sig> end) :
             sig
               structure X : <sig>
               val XHTML_Header : string
               val HTML : X.tag
               val HEAD : X.tag
               val TITLE : X.tag
               val BODY : X.tag
               val H1 : X.tag
               val H2 : X.tag
               val H3 : X.tag
               val H4 : X.tag
               val H6 : X.tag
               val P : X.tag
               val ADDRESS : X.tag
               val buildRef : string -> X.tag
               val comment : string -> string
               val +++ : X.xmltree * X.xmltree -> X.xmltree
               val <<< : X.tag * X.xmltree -> X.xmltree
               val ! : X.tag * X.parameter list -> X.tag
               val $ : string -> X.xmltree
             end
structure Combinators : XML_COMBINATORS
structure Xhtml : XHTML
- open Xhtml;
opening Xhtml
  structure X :
    sig
      type parameter = string * string
      type tag = string * parameter list
      datatype xmltree
        = Concat of xmltree * xmltree
        | Inject of tag * xmltree
        | Str of string
        | Tag of tag
      val augment : tag * parameter list -> tag
      val buildString : string -> xmltree
      val buildTag : string * (string * string) list -> tag
      val flatten : xmltree -> string
    end
  val XHTML_Header : string
  val HTML : X.tag
  val HEAD : X.tag
  val TITLE : X.tag
  val BODY : X.tag
  val H1 : X.tag
  val H2 : X.tag
  val H3 : X.tag
  val H4 : X.tag
  val H6 : X.tag
  val P : X.tag
  val ADDRESS : X.tag
  val buildRef : string -> X.tag
  val comment : string -> string
  val +++ : X.xmltree * X.xmltree -> X.xmltree
  val <<< : X.tag * X.xmltree -> X.xmltree
  val ! : X.tag * X.parameter list -> X.tag
  val $ : string -> X.xmltree
- ^D

--------------------------------------------------------------------
And the code in question. If you want it for http download in the
future, then do please tell:


signature XML = 
sig

 type parameter
 (* 
  * TODO Build up a tagtype, which sets options on where a given
  * tag can be used 
  *)
 type tag

 datatype xmltree = Str of string
                  | Tag of tag
                  | Concat of xmltree * xmltree
                  | Inject of tag * xmltree

 val augment : tag * parameter list -> tag

 val buildString : string -> xmltree
 val buildTag : string * ((string * string) list) -> tag

 val flatten : xmltree -> string

end

structure Xml : XML = 
struct

type parameter = (string * string)
type tag = (string * parameter list)

datatype xmltree = Str of string
                 | Tag of tag
                 | Concat of xmltree * xmltree
       		 | Inject of tag * xmltree

fun augment ((tagname, params), nparams) = 
    (tagname, params @ nparams)

fun buildString str = Str str

fun buildTag (name, paramlist) = (name, paramlist)

fun buildParamlist params = 
  String.concat (
    map (fn (param, value) => 
           String.concat [param, "=\"", value, "\" "]
        ) params
  )

fun flatten x =
  case x of
    Str str => str
  | Tag (str, params) => 
     String.concat ["<", str, " ", buildParamlist params, "/>"]
  | Concat (t1, t2) =>
     String.concat [flatten t1, flatten t2]
  | Inject ((str, params), tree) =>
     String.concat ["<", str, " ", buildParamlist params, ">",
                    flatten tree,
                    "</", str, ">"
                   ]

end

signature XML_STRUCTS =
sig
  structure Xml : XML
end

signature XML_COMBINATORS =
sig 

include XML_STRUCTS

val +++ : Xml.xmltree * Xml.xmltree    -> Xml.xmltree
val <<< : Xml.tag * Xml.xmltree        -> Xml.xmltree
val !   : Xml.tag * Xml.parameter list -> Xml.tag
val $   : string 		       -> Xml.xmltree

end

functor XmlCombinators (structure Xml : XML) : XML_COMBINATORS =
struct

structure Xml = Xml

infix 3 +++ (* Concatenation *)
infix 5 <<< (* Injection *)
infix 7 !   (* Augmentation *)

fun xt1 +++ xt2 = Xml.Concat (xt1, xt2)
fun tag <<< xt = Xml.Inject (tag, xt)
fun tag ! paramlist = Xml.augment (tag, paramlist)  
fun $ str           = Xml.buildString str
 
end


signature XHTML_STRUCTS =
sig

structure X : XML

end

signature XHTML =
sig

include XHTML_STRUCTS

val XHTML_Header : string
val HTML : X.tag
val HEAD : X.tag
val TITLE : X.tag
val BODY : X.tag
val H1   : X.tag
val H2   : X.tag
val H3	 : X.tag
val H4   : X.tag
val H6   : X.tag
val P    : X.tag
val ADDRESS : X.tag

val buildRef : string -> X.tag
val comment  : string -> string

val +++ : X.xmltree * X.xmltree        -> X.xmltree
val <<< : X.tag     * X.xmltree        -> X.xmltree
val !   : X.tag     * X.parameter list -> X.tag
val $   : string		       -> X.xmltree

end
functor Xhtml (structure XmlCombinators : XML_COMBINATORS) : XHTML =
struct

structure X = XmlCombinators.Xml

(*
 * This could be rewritten into the XML code but this is simpler for
 * the time being
 *)

val XHTML_Header = 
  String.concatWith "\n" [
     "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
     "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 0.1//EN\"",
     "  \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"
  ]

val HTML = X.buildTag 
    ("html", [("xmlns", "http://www.w3.org/1999/xhtml"),
              ("xml:lang", "en")
             ])

val HEAD = X.buildTag ("head", [])
val TITLE = X.buildTag ("title", [])
val BODY = X.buildTag ("body", [])
val H1   = X.buildTag ("h1", [])
val H2   = X.buildTag ("h2", [])
val H3   = X.buildTag ("h3", [])
val H4   = X.buildTag ("h4", [])
val H6   = X.buildTag ("h6", [])
val P    = X.buildTag ("p", [])
val ADDRESS = X.buildTag ("address", [])

fun buildRef r = X.buildTag ("a", [("href", r)])
fun comment com = String.concat ["<!-- ", com, "-->"]
 
val +++ = XmlCombinators.+++
val <<< = XmlCombinators.<<<
val !   = XmlCombinators.!
val $   = XmlCombinators.$

val flatten = X.flatten


end

structure Combinators = XmlCombinators(structure Xml = Xml)

structure Xhtml = Xhtml(structure XmlCombinators = Combinators)

(*
structure MyHomepage = J_Mongers_Org(structure Xhtml = Xhtml)
*)



-- 
j. 



-------------------------------------------------------
This SF.net email is sponsored by: SF.net Giveback Program.
SourceForge.net hosts over 70,000 Open Source Projects.
See the people who have HELPED US provide better services:
Click here: http://sourceforge.net/supporters.php
_______________________________________________
MLton-devel mailing list
MLton-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mlton-devel