Recursive Anonymous Functions in SML

Is it possible to write recursive anonymous functions in SML? I know I can just use the fun syntax, but I'm curious.

I wrote as an example of what I want:

 val fact = fn n => case n of 0 => 1 | x => x * fact (n - 1) 
+7
source share
4 answers

An anonymous function is no longer anonymous when you bind it to a variable. And since val rec is just a derivative of fun without any other appearance than it, you could just write it using the fun syntax. You can also match patterns in fn expressions as in case , since the cases are derived from fn .

So in all its simplicity you could write your function as

 val rec fact = fn 0 => 1 | x => x * fact (x - 1) 

but this is the same as below more readable (in my oppion)

 fun fact 0 = 1 | fact x = x * fact (x - 1) 

As far as I think, there is only one reason to use the code for writing using long val rec , and that is because you can make it easier to comment on your code with comments and forced types. For example, if you saw the Haskell code before and just like they type annotation of their functions, you could write something like this

 val rec fact : int -> int = fn 0 => 1 | x => x * fact (x - 1) 

As mentioned above, you can do this using a fixed combinator point. Such a combinator may look like

 fun Y f = let exception BlackHole val r = ref (fn _ => raise BlackHole) fun ax = !rx fun ta f = (r := f ; f) in ta (fa) end 

And you could then calculate fact 5 with the code below, which uses anonymous functions to express the function of the teacher, and then binds the result of the calculation to res .

 val res = Y (fn fact => fn 0 => 1 | n => n * fact (n - 1) ) 5 

Fixed-point code and sample calculation are kindly provided by Morten Brons-Pedersen.


Updated answer to George Kangas answer:

In languages ​​that I know, a recursive function will always be bound to a name. A convenient and ordinary way is provided by keywords such as "define", "let" or "letrec", ...

Trivially true by definition. If a function (recursive or not) is not associated with a name, it will be anonymous.

An unconventional, more anonymous look is the lambda binding.

I don’t see what is unconventional regarding anonymous functions, they are used all the time in SML, infact in any functional language. Its even starting to appear in more and more imperative languages.

Jesper Reenberg's answer shows the lambda binding; The "anonymous" function is bound to the names "f" and "fact" from lambdas (called "fn" in SML).

An anonymous function is actually anonymous (not "anonymous" - without quotes), and yes, of course, it will be tied to the area that the function will ever be passed as an argument. In any other cases, the language would be completely useless. The same thing happens when calling map (fn x => x) [.....] , in this case the anonymous identification function is still anonymous.

The "usual" definition of an anonymous function (at least according to wikipedia ), saying that it should not be tied to an identifier, is a little weak and should include an implicit operator "in the current environment".

This is true for my example, as you can see by running it in mlton with the -show-basis argument in a file containing only fun Y ... and val res ..

 val Y: (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b val res: int32 

From this it is clear that not one of the anonymous functions is connected in the environment.

A shorter alternative to "lambdanonymous" that requires running OCaml with "ocaml -rectypes":

 (fun fn -> ffn) (fun fn -> if n = 0 then 1 else n * (ff (n - 1)) 7;; Which produces 7! = 5040. 

It seems that you completely misunderstood the idea of ​​the original question:

Is it possible to write recursive anonymous functions in SML?

And the simple answer is yes. The tricky answer (among others?) Is an example of this, made using a fixed-point combinator, rather than "lambdanonymous" (what is it ever implied), an example made in another language using features that cannot even be removed in SML .

+12
source

All you have to do is put rec after val , as in

 val rec fact = fn n => case n of 0 => 1 | x => x * fact (n - 1) 

Wikipedia describes this at the top of the first section.

+8
source
 let fun fact 0 = 1 | fact x = x * fact (x - 1) in fact end 

This is a recursive anonymous function. The name "fact" is used only internally.

Some languages ​​(such as Coq) use "fix" as a primitive for recursive functions, and some languages ​​(such as SML) use recursive-let as a primitive. These two primitives can encode each other:

 fix f => e := let rec f = e in f end let rec f = e ... in ... end := let f = fix f => e ... in ... end 
+1
source

In languages ​​that I know, a recursive function will always be bound to a name. A convenient and ordinary way is provided by keywords such as "define", "let" or "letrec", ...

An unconventional, more anonymous look is the lambda binding. Jesper Reenberg's answer shows the lambda binding; the "anonymous" function is bound to the names "f" and "fact" by lambdas (called "fn" in SML).

A shorter alternative to "lambdanonymous", for which OCaml is started using "ocaml -rectypes":

 (fun fn -> ffn) (fun fn -> if n = 0 then 1 else n * (ff (n - 1)) 7;; 

That gives 7! = 5040.

-one
source

All Articles