Different ways of declaring a function - list

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]

Related

Find max value in list of `(string * int) list`

I have a list of (string * int) list elements and I need to find the biggest int element and return the corresponding(string * int) element.
I have something like this atm, but problem is, I think my approach is more of "typical programming"
let it = [] in
for x = 0 to length LIST - 1 do
let str = ((List.nth LIST x).string) in
let num = ((List.nth LIST x).int) in
let it = it # [num, str] in
let (str, num) = List.hd(List.rev it) in
[str, num]
What I tried to do is to loop through the list and add the string and int value in another list, then sort them, reverse it and then take the head, which should be the max int, then I need to return the pair in (string * int)
Your code is not a well-formed OCaml code. It highlights, however, some number of issues with your understanding of OCaml.
First of all, by default, values in OCaml are immutable. For example,
let x = 0 in
for i = 0 to 10 do
let x = x + 1 in
print_int x;
done
You will get 11111111111 as the output. This is because, during the loop, you are just computing every time the x+1 expression, where x is always 0 and you will always get 1 as the result. This is because, let x = <expr> in <body> is not changing the existing variable x but is creating a new variable x (shadowing any previous definitions) and make it available in the scope of the <body> expression.
Concerning your problem in general, it should be solved as a recursive function greatest_element, which has the following definition,
for an empty list [] it is undefined;
for a list of one element [x] is it is x;
otherwise, for a list of x::xs it is max x (greatest_element xs),
where max x y is x if it is greater or equal to y.
Finally, it looks like you have missed the first steps in OCaml and before solving this task you have to move back and to learn the basics. In particular, you have to learn how to call functions, bind variables, and in general what are the lexical conventions and syntax of the language. If you need pointers, feel free to ask.
First of all, it doesn't seem that you did any kind of sorting in
the code that you provided.
Assuming that your list is of type
(string * int) list then a possible to find the element with the
maximum integer using recursion:
let max_in_list list =
let rec auxiliary max_str max_int = function
| []
-> (max_str, max_int)
| (crt_str, crt_int)::tail when crt_int > max_int
-> auxiliary crt_str crt_int tail
| _::tail
-> auxiliary max_str max_int tail
in
match list with
| []
-> None
| (fst_str, fst_int)::tail
-> Some (auxiliary fst_str fst_int tail)
let check = max_in_list [("some", 1); ("string", 3); ("values", 2)]
You could write a generic maxBy function. This allows you to get the max of any list -
let rec maxBy f = function
| [] -> None
| [ x ] -> Some x
| x :: xs ->
match (maxBy f xs) with
| Some y when (f y) > (f x) -> Some y
| _ -> Some x
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)
let data = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]
(* val data : (string * int) list = [("a", 3); ("b", 2); ("c", 6); ("d", 1)]*)
maxBy (fun (_, num) -> num) data
(* - : (string * int) option = Some ("c", 6) *)
maxBy (fun (str, _) -> str) data
(* - : (string * int) option = Some ("d", 1) *)
maxBy (fun x -> x) [3; 2; 6; 1]
(* - : int option = Some 6 *)
maxBy (fun x -> x) ["c"; "d"; "b"; "a"]
(* - : string option = Some "d" *)
maxBy (fun x -> x) []
(* - : 'a option = None *)
It can be fun to rewrite the same function in various ways. Here's another encoding -
let maxBy f list =
let rec loop r = function
| [] -> r
| x::xs when (f x) > (f r) -> loop x xs
| _::xs -> loop r xs
in
match list with
| [] -> None
| x::xs -> Some (loop x xs)
(* val maxBy : ('a -> 'b) -> 'a list -> 'a option = <fun> *)

Memoization list Ocaml

I have a recursive function and I want the rewriting in the Mémoïsant
My recursive function:
let rec sum_cube l =
match l with
| [] -> 0
| x :: s -> (x * x * x) + sum_cube s
and I tried with this:
let memo = Hashtbl.create 17
let rec sum_cub_memo l =
try
Hashtbl.find memo l
with Not_found ->
let fn = function
| [] -> 0
| x::s -> (x * x * x ) sum_cub_memo s
in
Hashtbl.add memo l fn
fn ;;
I have an error:
This expression has type int list -> int but an expression was expected of type int list!!
You should memoize not the function, but the result of the function, e.g., using your definition of sum_cube:
let sum_cube_memo xs =
try Hashtbl.find memo xs with Not_found ->
let res = sum_cube xs in
Hashtbl.add memo xs res;
res
This will work, however there is a caveat. You're using a list of integers as a key. That means, that first the key is transformed to its hash (basically O(n), and will take basically the same amount of time as computing the power of three), second, if there is a hash collision, then every list in the bucket will be compared with the argument list. As a result, your memoized function has the same complexity as your non-memoized function, it has worse performance, and also consumes unbound amount of memory. Is it worthwhile?
sum_cube without memorization.
let sum_cube l =
let cube x =x*x*x in
List.fold_left ( fun acc x -> acc+cube x) 0 l
sum_cube with memorization and trace.
let sum_cube l =
let memo = Hashtbl.create 17 in
let cube_memo x =
try
let xcube= Hashtbl.find memo x in
Printf.printf "find %d -> %d\n" x xcube;
xcube
with Not_found ->
let xcube=x*x*x in
Printf.printf "add %d -> %d\n" x xcube;
Hashtbl.add memo x xcube;
xcube
in
List.fold_left ( fun acc x -> acc+cube_memo x) 0 l
Test :
# sum_cube [4;4;2;3;4;2];;
add 4 -> 64
find 4 -> 64
add 2 -> 8
add 3 -> 27
find 4 -> 64
find 2 -> 8
- : int = 235

Combining two functions in OCaml

My task is to remove the duplicates from a list. To do that I have to first sort the list.
I have written the function that sorts the list and the one that remove the
duplicates(once they are sorted) but I don't know how to combine them.
Example:
input: [4;5;2;2;1;3;3]
output: [1;2;3;4;5]
let rec setify = function
| [] -> []
| x :: l -> insert x (setify l)
and insert elem = function
| [] -> [elem]
| x :: l -> if elem < x then elem :: x :: l
else x :: insert elem l;;
let rec rem =function
|[] -> []
| x :: []-> x :: []
| x :: y :: rest -> if x = y then rem (y :: rest)
else x :: rem (y :: rest) ;;
You want to make the function that takes a list, creates the sorted list, and deduplicates that. In other words, you want:
let task list =
let sorted_list = setify list in
rem sorted_list
It is possible to do this in arbitrarily more complicated ways, but the above is one straightforward, one-action-per-line version. Since the phrasing of the title of your question invites it, here is one of the more sophisticated ways:
(* it's possible to write a generic combinator of functions, that takes two functions f and g *)
let combine f g =
(* and returns a function *)
fun x ->
(* that maps x to f(g(x)) *)
f (g x)
(* this function is typed as:
val combine : ('a -> 'b) -> ('c -> 'a) -> 'c -> 'b = <fun>
*)
(* the task can then be expressed as the combination of setify and rem: *)
let task = combine rem setify
Don't use this style unless something is actually gained from it. Most of
the times it only makes programs less readable and slower with no corresponding benefit. *)

how to rewrite code using tail recursion

I just looking for a little advice, how to rewrite code using tail recursion
open Core.Std;;
let rec dig x =
match x with
| 0 -> []
| _ -> x :: dig (x - 1)
;;
let () =
let numbers = dig 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Any advice will be helpful
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (x::s)
f x []
Is this what you want? It's using tail recursion.
Edit:
for a decreasing seq, just replace (x::s) with (List.append s [x]) or (s # [x]) but it's NOT a good idea,and List.rev is better:
let dig x =
let rec f x s =
match x with
| 0 -> s
| _ -> f (x-1) (s # [x])
f x []
let dig x =
let rec f s z =
if z = x then s
else f (z::s) (z+1)
in
f [] 0
not sure if this floats your boat: You may have to tweak the border cases depending if you want 0 or the starting number included.
If you don't want to use List.rev after building the list backwards (which in my opinion is perfectly fine), nor starting your recursion with 0 instead of n, you can use some kind of continuation:
let dig2 x =
let rec aux x kont =
match x with
| 0 -> kont
| _ -> aux (x-1) (fun l -> kont (x::l))
in
aux x (fun l -> l) [];;
Basically each step returns a function that, given the list built by the remaining steps, will append x to it. We start the recursion with the identity function since we don't have anything to build yet. Then, when we exit from the recursion, we thus just have to apply the empty list to the obtained function.
Well, it seems to can have multiple solutions
open Core.Std;;
let rec digtail ?(l=[]) x =
match x with
| 0 -> l
| _ -> digtail ~l: (l # [x]) (x - 1)
;;
let () =
let numbers = digtail 10 in
List.iter ~f:(Printf.printf "%d, ") numbers;
Printf.printf "\n";
;;
Thanks to all, you helped a lot.

OCaml error filter list using higher order functions

So I have this exercise:
filter (fun x -> x = 0) [(1,0);(2,1);(3,0);(4,1)];;
result int list [1;3]
So basically you have to match your x in fun with the second number in list and if its the same you create new list with the first number.
My solution but is wrong
let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [];;
I get the following error when i want to try the code:
Error: This expression has type int but an expression was expected of
type
int -> bool
I can't reproduce the problem you report. Here's what I see when I try your code:
$ ocaml
OCaml version 4.02.1
# let rec filter f = function
| []->[]
| x::l -> if f=snd x then fst x :: filter f l else [] ;;
val filter : 'a -> ('b * 'a) list -> 'b list = <fun>
# filter 0 [(1,0); (2,1); (3,0)];;
- : int list = [1]
There are no errors, but it gets the wrong answer. That's what I would expect looking at your code.
The error that you are getting is saying that somewhere the compiler is expecting an int -> bool function, but you are giving it an int. The reason you get this error is because you have an equality (f = snd x), where f is of type int -> bool and snd x is of type int. both arguments given to the equality must be of the same type. Instead, what you want to do is simply branch on the result of applying f to the second element of x, such as:
let rec filter f = function
| []->[]
| x::l -> if f (snd x) then fst x :: filter f l else [];;
That said, I would recommend using pattern matching instead of fst and snd, such as:
let rec filter f l =
match l with
| [] -> []
| (x,y)::l -> if f y then x :: filter f l else filter f l
Note that f y will return something of type bool, which will then determine which branch to take.
Altough Matts answer is right. It's good to just reuse existing functions instead of writing a special from the ground up:
[(1,0);(2,1);(3,0);(4,1)]
|> List.filter (fun (_, x) -> x = 0)
|> List.map fst