How would I flatten a list of lists of integers into a single list of integers in ocaml? The function would work as shown below.
[[1;2];[3;4;5];[];[6]] -> [1;2;3;4;5;6]
As this is homework, it must be done using only fold_left or fold_right, and cannot use the '#' operator, and cannot use recursion. I get that the accumulator is going to be the members of the new list, but I have no clue how to actually move the elements of the original list to the accumulator. Any hints would be appreciated.
Here are some hints:
a. Moving a value to the accumulator is not difficult. If your value is x and your accumulator is a, you can just write x :: a.
b. You mostly need to process all the inner values in a consistent order. That's what folds are for.
c. A fold is for processing the elements of a list. But you have a list of lists.
List.fold_left (fun liRes la ->
List.fold_right ( fun iRes la ->
iRes::la
) liRes la
) [] [[1;2];[3;4;5];[];[6]]
result :
- : int list = [1; 2; 3; 4; 5; 6]
other form :
let (#) =
List.fold_right ( fun iRes la ->
iRes::la
);;
List.fold_left (fun liRes la ->
liRes # la
) [] [[1;2];[3;4;5];[];[6]];;
You can try :
# []#[1;2];;
- : int list = [1; 2]
# (#) [1;2] [3;4];;
- : int list = [1; 2; 3; 4]
Related
This Ocaml code traverses a list and outputs the last element.
I dont understand the second condition where we output Some x
let rec last = function
| [] -> None
| x::[] -> Some x
| _ :: t -> last t ;;
So if the list is empty we return null.
If x is the last element we return Some x (* what is Some x in this context? *)
If x is not the last element we go further in the list.
Some is a constructor for the option type. None is the other constructor. Consider the following definition of option.
type 'a option = None | Some of 'a
The net effect of this is to provide for functions to have an option to return a value, or a value representing nothing. Imagine I want to search for the index of an item in a list. What should I return if the value isn't in the list?
let find_index value lst =
let rec aux value lst idx =
match lst with
| [] -> None
| x::_ when x = value -> Some idx
| _::xs -> aux value xs (idx + 1)
in
aux value lst 0
utop # find_index 4 [1; 8; 2; 5; 4; 10];;
- : int option = Some 4
─( 17:10:49 )─< command 3 >──────────────────────────────────────{ counter: 0 }─
utop # find_index 4 [1; 8; 2; 5; 7; 10];;
- : int option = None
Both values have type int option so OCaml's type system is happy.
In your example, an empty list doesn't have a last element, so you return None.
We can then pattern match on this to handle the two situations:
let some_list = [2; 3; 4]
let () =
match last some_list with
| None -> print_endline "This list doesn't have a last item."
| Some item -> print_endline ("The last item found was " ^ string_of_int item)
You may have run into languages where this type of situations is handled by returning a special error value. We could return -1 for instance. Or we could throw a ValueNotFound exception.
I'm reading https://ocaml.org/learn/tutorials/99problems.html and it has 2 examples:
# let rec last_two = function
| [] | [_] -> None
| [x;y] -> Some (x,y)
| _::t -> last_two t;;
I understand the first one: _::t means pattern match anything and call it t
But at
# let rec at k = function
| [] -> None
| h :: t -> if k = 1 then Some h else at (k-1) t;;
I don't understand what h means. For me it should be _:: t -> ... to match anything and call it t
The pattern _ :: t doesn't mean what you say. It matches any non-empty list and calls the tail of the list t.
The pattern h :: t matches any non-empty list, calls the head of the list h (one element, the first one), and the tail of the list t (zero or more elements after the first one).
The operator :: is the list constructor (often called "cons"), which is why these patterns match lists.
Here are examples of :: as list constructor:
# true :: [];;
- : bool list = [true]
# 1 :: [2; 3];;
- : int list = [1; 2; 3]
As is usual in OCaml, the pattern for a list uses the same syntax as the constructor.
# match [1;2;3] with [] -> None | h :: t -> Some (h, t);;
- : (int * int list) option = Some (1, [2; 3])
The h::t pattern matches the head and tail of the list to the variables h and t.
So if I pattern match like this:
match [1; 2; 3] with
| h::t -> (* Some code... *)
h will have a value of 1, and t will have the value of [2; 3].
:: is a constructor. Pattern matching in this fashion pattern matches against constructors. They create a new datatype out of two values. :: is a constructor, and its type, list, is recursive. Here's a sample definition of the list type:
type 'a list =
| []
| (::) 'a * ('a list)
;;
So the list type is recursive because its constructor, ::, calls itself.
Honestly, I could write half a book on lists. They're the bread and butter of functional programming languages.
If you're wondering why you can't pattern match on operators, this is why. You can't pattern match on operators, only constructors.
Yes, indeed when you type in a function let's take for example this one:
let is_empty (l: int list) : int =
begin match l with
| [] -> 1
| h::t -> 0
end;;
Therefore, in this function that tests if a list is empty or not, if [], an empty list it returns one or in boolean true but if h::t, meaning that there is one or more value, the function returns 0, meaning it's false.
This is what I want to achive, to return to a list with values that are below the given value with recursion:
# list_below 3 [7; 1; 0; 3];;
- : int list = [1; 0]
# list_below 1 [-7; 1; 0; 3];;
- : int list = [-7; 0]
# list_below 9.0 [4.2; 3.6; 5.0; 12.8];;
- : float list = [4.2; 3.6; 5.0]
Here is what I wrote so far, and it does not appear to return anything.
let rec list_below thresh lst =
if List.hd lst > thresh then [] else
List.hd lst :: list_below thresh (List.tl lst);;
;;
Could you show me what is wrong with my code?
The problem should be what Jeffrey has pointed out for you.
Your questions says you want to implement list_below, but your code shows list_above. I'll stick to list_below here.
Recursive functions in Ocaml can be made quite intuitively if you use pattern matching. For example, the below code should work :
let rec list_below thresh lst =
match lst with
| [] -> []
| hd :: tl -> if hd < thresh then hd :: (list_below thresh tl)
else list_below thresh tl;;
If the first value is above the threshhold your code always returns an empty list. That can't be right. It is inconsistent with your first example, for one thing.
You could try using List.filter. Since you want to get a list of values that are less than the supplied value, then filter should do what you want.
Here's the documentation for filter:
val filter : ('a -> bool) -> 'a list -> 'a list
filter p l returns all the elements of the list l that satisfy the predicate p. The order of the elements in the input list is preserved.
What you need is to provide a predicate p. A predicate is a function that takes an element and returns a boolean. Filter will take this predicate and apply to each value in the list. If the predicate returns true for that element, the element will be added to the resulting list.
So in your case, list_below should be
let list_below thresh lst =
List.filter (fun elem -> elem < thresh) lst
More more operations on list, check out this chapter in Real World OCaml.
Here is my code:
let rec size = function
| [] -> 0
| t::q -> 1 + size q
let rec n k v lst = match lst with
| [] -> None
| t::q when (v - size q) = k -> t
| _::q -> n k v q
let () = print_int (n (3) (5) ([ 1 ; 2; 3; 4; 5 ]) )
It's saying the following:
File "main.ml", line 10, characters 33-34:
Error: This expression has type int but an expression was expected of type
'a option
I don't understand what it means.
I am trying to print the nth element of a list. I mean print_int is waiting for an int and k, v are integers.
The first case of your function n returns None whose type is 'a option.
You then proceed to return t, therefore the compiler deduce t must also be of type 'a option.
You should use the constructor Some when returning t:
let rec n k v lst = match lst with
|[] -> None
|t::q when (v - size q) = k -> Some t
|_::q -> n k v q
You won't however be able to use it with print_int right away, you will have to unpack the option type in the following way:
let () = match (n (3) (5) ([ 1 ; 2; 3; 4; 5 ]) ) with
| Some v -> print_int v
| None -> ()
Your function n has type int -> int -> 'a option list -> 'a option because in the first case
| [] -> None
you're returning None that is a value of type 'a option, and on the second case
|t::q when (v - size q) = k -> t
you're returning an element of the list. Since a function can have only one return type, the type inference algorithm unifies the type of the list elements with the option type, thus requiring the input list elements to have type 'a option
The print_int function accepts values of type int, but you're passing something that is 'a option that is not an int. Moreover, if you will remove print_int then the following expression won't type either:
let _ = n 3 5 [1;2;3;4;5]
because your n function accepts a list of options, not a list of integers, e.g.,
let _ = n 3 4 [Some 1; Some 2; None; None]
What is the difference between map and collect? documentation below - i cant tell the difference..
List.map<'T,'U> Function
Creates a new collection whose elements are the results of applying the given function to each of the elements of the collection.
// Signature:
List.map : ('T -> 'U) -> 'T list -> 'U list
List.collect<'T,'U> Function
For each element of the list, applies the given function. Concatenates all the results and returns the combined list.
An example for illustration
Let's say you have a list of lists:
let list = [ [1; 2]; [3; 4]; [5; 6] ]
And a transformation function:
let trans = fun x -> [for i in x -> i*10]
List.map trans list will produce:
[[10; 20]; [30; 40]; [50; 60]]
While
List.collect trans list will produce:
[10; 20; 30; 40; 50; 60]
List.collect will apply the transformation function and will Concatenate the result while List.map will only apply the transformation function.
The difference is that the output list from map is the same length as the input list. For collect, the output list may be longer or shorter than the input as the function you pass returns a list instead of a single element.
For more detail - compare the signatures. For map
List.map : ('T -> 'U) -> 'T list -> 'U list
and collect
List.collect : ('T -> 'U list) -> 'T list -> 'U list
you can see here that the return type of the function argument is different.
Adding to #John's answer, the difference is in the word Concatenates.
Basically, List.collect f xs is the same as List.concat (List.map f xs).