How do you define functions and values depending on each other in Standard ML?
The following program:
val cmds = [("help", cmd_help)];
fun cmd_help () = List.app (fn cmd => print (#1 cmd ^ "\n")) cmds;
cmd_help ();
Does not compile:
$ mlton example.sml
Error: example.sml 1.22-1.29.
Undefined variable: cmd_help.
Is it possible to define cmds and cmd_help such that they both know about each other and are also exposed as top-level definitions to the rest of the program?
Interesting question, the most obvious way would be to make
cmdsa unitary function, and then call that incmd_helpjust like a normal pair of recursive functions.One would expect that you could reverse the situation, treating
cmds_helpas a value. Indeed the syntax even appears to parse.However, it doesn't actually compile when you add mutual recursion into the works (I tried the following with MLton and smlnj). Manually declaring types because the inference wasn't doing particularly well.
This last case results in:
So the question now is, why doesn't this work If we look at the section Value Bindings, on pg 42 of The Definition of Standard ML (Revised) in the footnote 25 it says
So while
andfor functions allows mutual recursion,andfor values allows ensures that the values environments are disjoint.Alas, I don't know how to do this without promoting a value to a function.