[MLton-user] type-indexed values

Stephen Weeks sweeks@sweeks.com
Mon, 7 Aug 2006 13:31:07 -0700


I read through

  http://mlton.org/TypeIndexedValues

and have a few suggestions (other than using tupling instead of
currying :-).

* I don't think there is any benefit from conflating the types

    ('a, c) t  
    ('a, 'k p) t
    ('a, s) t

  One can see this from the absence of any function that operates on a
  value of type

    ('a, 'b) t
  
  So, I propose the following substitutions:

    ('a, c) t --> 'a t
    ('a, 'k p) t --> ('a, 'k) p
    ('a, s) t --> 'a s

  The only remaining phantom types are "u" and "l", which allow "*" to
  be used for both labeled and unlabeled products.

* I wonder if it would be useful to combine all of the utility
  functions (const, cross, curry, ...) onto a single wiki page, as
  they are being used more and more across different pages.

* I think it would be nice to use some name other than "T" for the
  fixed-point value, since T is so commonly used for the
  single-variant constructor.  I can understand the desire for a
  single-letter name, although I think that "fix" wouldn't be so bad.
  Perhaps "R" or "F"?

* It would be nice for the array/ref stuff to handle sharing, not just
  cycles.

* A combinator that I find useful for writing one-off loops is

    val recur: 'a * ('a * ('a -> 'b) -> 'b) -> 'b
    fun recur (a, f) = let fun loop a = f (a, loop) in loop a end 

  This could be used to good effect in replacing the "lp" functions.

  The advantages of recur over the SML "let fun" syntax is that one can
  write a single expression, can avoid dropping out to the declaration
  level, and the code for initializing the loop variables is
  syntactically close to the binding of the loop variables.

  Compare

     let
        fun f (x, y) = 
           ... f (a, b) ...
     in
        f (1, 2)
     end

  with

     recur 
     ((1, 2), fn ((x, y), f) =>
      ... f (a, b) ...)

  If one is not already in the middle of declarations, or if the code
  for the body of "f" is large, recur improves readability.

* Is registering a show function for the basic exceptions (Bind, Chr,
  Div, ...) necessary?  It seems like General.exnName does the right
  thing.  Somewhat related, would it be better to move the default exn
  show function (using General.exnName) into the initial registration
  for exceptions?

     regExn (fn Fail s => ...
              | _ => C0 (concat ["<exn:", ...]))