'How can you make a function that returns a function in ocaml

for an example, if a function receives a function as a factor and iterates it twice

func x = f(f(x))

I have totally no idea of how the code should be written



Solution 1:[1]

You just pass the function as a value. E.g.:

let apply_twice f x = f (f x)

should do what you expect. We can try it out by testing on the command line:

utop # apply_twice ((+) 1) 100
- : int = 102

The (+) 1 term is the function that adds one to a number (you could also write it as (fun x -> 1 + x)). Also remember that a function in OCaml does not need to be evaluated with all its parameters. If you evaluate apply_twice only with the function you receive a new function that can be evaluated on a number:

utop # let add_two = apply_twice ((+) 1) ;;
val add_two : int -> int = <fun>
utop # add_two 1000;;
- : int = 1002

Solution 2:[2]

To provide a better understanding: In OCaml, functions are first-class values. Just like int is a value, 'a -> 'a -> 'a is a value (I suppose you are familiar with function signatures). So, how do you implement a function that returns a function? Well, let's rephrase it: As functions = values in OCaml, we could phrase your question in three different forms: [1] a function that returns a function [2] a function that returns a value [3] a value that returns a value

Note that those are all equivalent; I just changed terms. [2] is probably the most intuitive one for you.

First, let's look at how OCaml evaluates functions (concrete example):

let sum x y = x + y
(val sum: int -> int -> int = <fun>)

f takes in two int's and returns an int (Intuitively speaking, a functional value is a value, that can evaluate further if you provide values). This is the reason you can do stuff like this:

let partial_sum = sum 2
(int -> int = <fun>)


let total_sum = partial_sum 3 (equivalent to: let total_sum y = 3 + y)
(int = 5)

partial_sum is a function, that takes in only one int and returns another int. So we already provided one argument of the function, now one is still missing, so it's still a functional value. If that is still not clear, look into it more. (Hint: f x = x is equivalent to f = fun x -> x) Let's come back to your question. The simplest function, that returns a function is the function itself:

let f x = x 
(val f:'a -> 'a = <fun>)
f 
('a -> 'a = <fun>)

let f x = x Calling f without arguments returns f itself. Say you wanted to concatenate two functions, so f o g, or f(g(x)):

let g x = (* do something *)
(val g: 'a -> 'b)
let f x = (* do something *)
(val f: 'a -> 'b)
let f_g f g x = f (g x)
(val f_g: ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>)

('a -> 'b): that's f, ('c -> 'a): that's g, c: that's x.

Exercise: Think about why the particular signatures have to be like that. Because let f_g f g x = f (g x) is equivalent to let f_g = fun f -> fun g -> fun x -> f (g x), and we do not provide the argument x, we have created a function concatenation. Play around with providing partial arguments, look at the signature, and there will be nothing magical about functions returning functions; or: functions returning values.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 lambda.xy.x