The application operator in Standard ML
In the previous post I introduced the $ operator to OCaml using two different approaches:
- Renaming the operator to
**$or@$in order to achieve the necessary associativity. - Leveraging Camlp4 to provide a syntax extension.
In the comments section1, variants of these operators were provided that mirror Haskell’s relative precedence of application and composition.
As a postscript, I thought it might be interesting to look at the implementation of $ in Standard ML. Here it is in the SML/NJ toplevel,
Standard ML of New Jersey v110.74 [built: Wed Apr 11 13:33:07 2012]
- infixr 0 $;
infixr $
- fun (f $ x) = f x;
val $ = fn : ('a -> 'b) * 'a -> 'b
Of note:
- Standard ML lets us specify the associativity of newly defined operators explicitly (using the
infix*fixity directives) whereas OCaml follows an operator naming convention. - As such, we have no need to fall back on syntax extensions here;
$is a valid name for a right associative operator.
To replicate the target example of the previous post we’ll need to define a few utilities,
- fun succ x = x + 1;
val succ = fn : int -> int
- val sum = foldl op+ 0;
val sum = fn : int list -> int
- fun printLn str = print $ str ^ "\n";
val printLn = fn : string -> unit
Note that printLn is defined using $; the standard approach would be fun printLn str = print (str ^ "\n").
With these definitions in place, we can employ $ to print the desired result:
- printLn $ Int.toString $ succ $ sum [1, 2, 3];
7
val it = () : unit
Finally, since $ was defined with a precedence level of 0, it interacts correctly with SML’s composition operator, o, which has a precedence of 3 (as per the Standard):
- printLn o Int.toString $ succ $ sum [1, 2, 3];
7
val it = () : unit
See the closing Update.↩
comments powered by Disqus