[MLton] associativity of &

Vesa Karvonen vesa.karvonen@cs.helsinki.fi
Fri, 24 Mar 2006 09:57:55 +0200


Quoting Stephen Weeks <sweeks@sweeks.com>:
> In writing up the fold stuff, I wondered about the decision to make
> the "&" of product types be infix left, rather than infix right.
> 
>   datatype ('a, 'b) prod = & of 'a * 'b
>   infix  4 &
> 
> What was the reason behind that decision?

I came up with the infix & when I came up with the for-loop combinators
(http://mlton.org/ForLoops - I should really add the >>= operator to that
page).  In that context the choice between infix & and infixr & can be
made fairly arbitrarily (there may be some performance implications (one
way or the other), but I don't have the time to think about them at the
moment).

I recall thinking about whether infix & or infixr & was better, but I
don't recall any particular technical reason for choosing infix &.

> I think it might be better
> to make "&" infix right.  By analogy with lists, in which :: is infix
> right, it is easier to recur over products via a fold left if they
> look like
> 
>   1 & (2 & (3 & (4 & ())))
> 
> rather than
> 
>   ((((1 & 2) & 3) & 4) & ())

Yes, I recently toyed with the idea of implementing Joy-like combinators
(http://www.latrobe.edu.au/philosophy/phimvt/joy.html) in SML and I used
infixr & for the same reason.  (See the code below.)  infixr & may indeed
be overall the better choice.

> With "&" infix right, constructing product via a fold left is slightly
> trickier, because one has to construct a function that fills a "hole"
> in the product, and apply that function at the very end.  But it's not
> too bad.

Maybe one could implement combinators to make it easy to use either
infix & or infixr &.

-Vesa Karvonen

(* Joy-like combinators
 *
 * These combinators do *not* quite capture Joy.  The dynamic
 * typing of Joy isn't easily translated to static H-M.
 *)

datatype ('a, 'b) c = & of 'a * 'b
infixr &

fun $ p = p
fun P ? k = k ?
fun % p f = P (f o p)
fun J k = k $
fun ` ? x = P? %(fn s => x & s)
fun dup ? = P? %(fn x & s => x & x & s)

fun uop ? uop = P? %(fn x & s => uop x & s)
fun bop ? bop = P? %(fn l & r & s => bop (l, r) & s)

fun neg ? = uop? ~
fun add ? = bop?op +
fun mul ? = bop?op *
fun sub ? = bop?op -
fun div' ? = bop?op div
fun mod' ? = bop?op mod
fun while' ? =
    P? %(fn st & pr & s =>
            let fun lp s = if hd (pr s) then s else lp (st s) in lp s end)
fun primrec ? =
    P? %(fn st & ba & n & s =>
            let fun lp (i, x & s) =
                    if i = n then x & s else lp (i+1, st (x & i+1 & s))
            in lp (0, ba s)
            end)

fun run p = (fn x & () => x) (p ())

val 3 = run (J `1 `2 add $)
fun fact ? = P? `(J `1 $) `(J mul $) primrec
fun sq ? = P? dup mul
val 120 = run (J `5 fact $)