[MLton-user] type-indexed values

Vesa Karvonen vesa.karvonen@cs.helsinki.fi
Tue Aug 8 13:31:40 PDT 2006


Quoting Stephen Weeks <sweeks@sweeks.com>:
> I read through
> 
>   http://mlton.org/TypeIndexedValues
> 
> and have a few suggestions (other than using tupling instead of
> currying :-).

Heh... :)

> * 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.

Nice simplification!  I can see that I still have a lot of signature
design heuristics to internalize.  BTW, the signature did contain
types of the form ('a, 'b) t earlier, but then, after a couple of
changes, all types of that form were eliminated.  (The use of phantom
types is a bit "academic" in this example, as they provide only a little
bit of protection.)

> * 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.

That would make sense.  Any suggestions for the title of such a page?
Suggestions: LittleUtilities, MiscUtilities, or perhaps
CollectedUtilities.

> * 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"?

I like Henry's suggestion: Y.  The ideas was that "T" stands for "Type"
or "Type-index", but that is probably too generic.

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

Yes and no.  Handling sharing does certainly make sense.  The code on
the page is meant to be a fairly complete (handles all kinds of types
including arbitrary user-defined datatypes) and fairly realistic (makes
practical sense) example of encoding type-indexed values.  Actually,
the main point of making the example is to explain a particularly nice
way (IMHO) to support arbitrary user defined datatypes.  I would leave
various improvements (sharing, pretty printing, optimizations) to an
actual library.  What kind of syntax would you suggest for showing
sharing?

> * 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.

Yes.  I noticed this in, IIRC, the Event implementation.  It made me wonder
whether there was some reason for not using a more traditional fixpoint
combinator.

>   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.

This reminds me of named let in Scheme.

> * Is registering a show function for the basic exceptions (Bind, Chr,
>   Div, ...) necessary?  It seems like General.exnName does the right
>   thing.

I considered that.  Defaulting to General.exnName is not a completely
satisfactory solution.  It does not distinguish between nullary and
unary exception constructors.  Also, General.exnMessage does not
necessarily generate SML syntax.

>   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:", ...]))

Probably not.  That would mean, AFAICS, that the code implementing exn
would then contain a hole.  That is, the exn implementation would have
to rely on the fact that there will always be at least one handler for
any exception.  That can't, AFAICS, be encoded conveniently using the
SML type system.  So, I prefer the currect organization of the code.

Thanks for the feedback!

-Vesa Karvonen




More information about the MLton-user mailing list