Decrypting return of function in OCaml - ocaml

I'am trying to decrypt the return of calc function below but i'am very confused.
I have the f function that takes 3 ints and returns an int.
The calc fuction i think should return val calc : int -> int = <fun> because f has to take 3 ints, i'am giving it x and y so now it needs one more to return another int, the final result. Why it this logic not correct?
I can't make any sense of the actual output, specially with the polymorfic values when i forced parameters in f to be integers.
# let f (x : int) (y : int) (z : int) = x + y + z;;
val f : int -> int -> int -> int = <fun>
# let calc x y f = f x y;;
val calc : 'a -> 'b -> ('a -> 'b -> 'c) -> 'c = <fun>

In the expression let calc x y f = f x y;;, f is a locally-bound variable (calc binds x, y and then f) rather than the function you have defined before.
If you had written let calc x y = f x y;; then you'd have the expected result.

The function calc contains no reference to the functionf. There is an argument named f be it could be named g without changing anything: let calc x y g = g x y. If you want to use the function f you have defined above and not any function of the right type, you must not pass f as an argument, you should rewrite calc like this:
let f x y z = x + y + z
let calc x y = f x y
and then calc will have the type int -> int -> (int -> int) which is more commonly written as int -> int -> int -> int.

Related

Different ways of declaring a function

When declaring a function, I've 3 different ways:
let f x = ...
let f = (fun x -> ...)
let f = function
| ... -> (pattern matching)
It's this last one that I don't fully understand how it works.
I was doing a function that, considering a list (we'll assume it has integers in it but could be anything), reverses it, pretty basic, but with a complexity of O(n). After struggling for an hour at least I check the answer, and it is written like this:
let reverse lst =
let rec aux acc = function
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
I thought that using the key word function was just another way of doing patter matching, but when I do this:
let reverse lst =
let rec aux acc =
match aux with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst
It doesn't work, and idk why. On top of that, why can we add tl at the end of the first function? Isn't aux a single argument function?
There are a few problems with this question. First, the code you give as the solution for reverse is not valid OCaml. It matches aux (which is a function) against list patterns. Most likely aux was supposed to be acc. But even so it doesn't seem right because it should have two arguments (the accumulated result and the input that still needs to be processed).
Second, your two code examples are the same. You seem to be saying that one works and one doesn't work. That doesn't make sense since they're the same.
IMHO you need to rewrite the question if you want to get a helpful answer.
Ocaml uses currying, which means that a two-argument function is the same thing that a function whose return value is a function.
To define a two-argument function, you can combine all the ways you know of creating one-argument functions:
let f x y = x + y
let f x = (fun y -> x + y)
let f x = function
| y -> x + y
let f = (fun x -> (fun y -> x + y))
let f = function
| x -> function
| y -> x + y
let f x = (let g y = x + y in g)
etc, etc.
All these definitions for f lead to the same result:
val f : int -> int -> int = <fun>
# f 3 4;;
- : int = 7
Note that the signature of f is:
val f : int -> int -> int = <fun>
If we added parentheses to better understand this signature, it would be this:
val f : int -> (int -> int) = <fun>
Meaning that f is a one-argument function whose return value is a one-argument function whose return value is an int.
Indeed, if we partially apply f:
# f 3;;
- : int -> int = <fun>
# let add_three = f 3;;
val add_three : int -> int = <fun>
# add_three 4;;
- : int = 7
The code you give at the end of your question is wrong. It's most likely intended to be this:
let reverse lst =
let rec aux acc l =
match l with
| [] -> acc
| hd :: tl -> aux (hd :: acc) tl
in
aux [] lst;;
val reverse : 'a list -> 'a list = <fun>
# reverse [1;2;3;4;5];;
- : int list = [5; 4; 3; 2; 1]

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

Is eta-expansion foolproof in OCaml?

Is it best to always eta-expand as a fool-proof rule of thumb in OCaml ?
type 'x recordx = { x : int }
type 'y recordy = { y : int }
let rec ok : type n a. n recordx -> a recordy -> int =
fun algebrah x -> ok algebrah x
let rec ok : type a. a recordy -> int =
fun x ->
let go : type b. b recordy -> int = ok in
go x
let rec ok : type n a. n recordx -> a recordy -> int =
fun x y ->
let go : type b. b recordy -> int = fun y -> ok x y in
go y
let rec ok : type n a. n recordx -> a recordy -> int =
fun x y ->
let go = ok x in
go y
(* This definition has type
'b recordy -> int which is less general than
'b0. 'b0 recordy -> int
*)
let rec ko : type n a. n recordx -> a recordy -> int =
fun x y ->
let go : type b. b recordy -> int = ko x in
go y
The relaxed value restriction classifies the eta-expanded form fun y -> f x y as a value that can thus be generalized by let bindings, contrarily to the non-value f y. See https://ocaml.org/manual/polymorphism.html#s%3Aweak-polymorphism .
Moreover, in a eager language like OCaml, eta-expansion does change the semantics of functions. Consider
let print x =
Format.printf "x=%s#." x;
fun y -> Format.printf "y=%s#."
and
let print1 = print "x"
let print2 y = print "x" y
Thus, eta-expansion is a semantic-changing transformation rather than a "foolproof" transformation.

OCaml Function that takes in functions

I need to write a pipe function in OCaml such that pipe [f1;...;fn] (where f1,...,fn are functions!) returns a function f such that for any x, f x computes fn(...(f2(f1 x))).
I need to write it using List.fold_left and need to fill in the parameter of the function
let pipe fs =
let f a x = "fill in this part" in
let base = fun x ->x in
List.fold_left f base fs;;
I already filled in the base. If the first parameter to pipe is an empty list, it returns the second parameter. Ex: pipe [] 3 = 3.
i know for the let f a x part I want to perform function x of the accumulated functions a.
I'm just not sure how to write that. I wrote let f a x = x a but that gave me an error when i tested
pipe [(fun x -> x+x); (fun x -> x + 3)] 3
it should run x+x on 3 then run x+3 on the result and give me 9 but it gave it a type error when i tried to use let f a x = x a
for the fill in part
# let _ = pipe [(fun x -> x+x); (fun x -> x + 3)] 3;;
File "", line 1, characters 24-25:
Error: This expression has type 'a -> 'a
but an expression was expected of type int
What is the correct format to create a function that takes in 2 functions and runs them on each other. Ex: make a function that takes in functions a and b and runs b on the result of a.
To evaluate (fold_left g init fs) x:
when fs is empty, (fold_left g init fs) x = init x. In your case, you want it to be x.
when fs = fs' # [fn]: according to what you would like to be true, the expression should evaluate to
fn (fold_left g init fs' x) but using the definition of fold_left it evaluates also to (g (fold_left g init fs') fn) x.
Hence if the following equations are true:
init x = x
(g k f) x = f (k x)
the problem is solved. Hence, let us define init = fun x -> x and
g k f = fun x -> f (k x).
Well, base is a function like this fun x -> ....
Similarly, your function f needs to return a function, so assume it returns something that looks like this:
fun z -> ...
You have to figure out what this function should be doing with its argument z.
figured it out just needed that z in there for a and x to call

How to get ` int -> (int -> int)`?

Are the two types: int -> int -> int and int -> (int -> int) the same?
If I write let f x = fun y -> x + y + 1, utop returns int -> int -> int. But I want is a function that takes an int as a parameter and then return a function which also takes an int and returns int, i.e., int -> (int -> int)
Is there a way to do that?
Also for (’a * ’b -> ’c) -> (’a -> ’b -> ’c), I wrote let f g = fun a b -> g (a,b), but it returns (’a * ’b -> ’c) -> ’a -> ’b -> ’c, the parentheses are eliminated. But why?
If a new function is returned as result, will it be anyway curried?
Usually, in lambda-calculus all functions have 1 arguments. Functions that take two arguments (not a tuple) are functions which take 1 argument and return another functions. If you look at the problem from this point of view you will understand that -> is right-associative.
Yes, they are the same. The arrow is a right-associative infix constructor, which is why the parentheses are redundant on the right.
It is perhaps helpful to realise that
let f x y z = e
is simply syntactic sugar for
let f = fun x -> fun y -> fun z -> e
Everything else follows form there.
Well yes, they are the same.
You can try it out, just type in
let f x y = x + y + 1;;
val f : int -> int -> int = <fun>
# let g = f 1;;
val g : int -> int = <fun>
# let _ = List.map g [1;2;3];; (* would do the same with (f 1) instead of g *)
- : int list = [3; 4; 5]
The whole idea is that function are by default curryfied. And as a -> ( b -> c ) and a -> b -> c are equivalent, they are displayed as the lightest type possible.