'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 |
