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