I am very new to F#, I am currently learning recursions.
let rec insert v i l =
match i, l with
| 0, xs -> v::xs
| i, x::xs -> x::insert v (i - 1) xs;;
So this is the code for inserting v at ith position in list l.
I want to repeat this process so that I can insert v at every ith position of list l.
For example, if I compile the following code:
insert 7 2 [1..10];;
I want the result list to be:
[1; 2; 7; 3; 4; 7; 5; 6; 7; 7; 8; 7; 9; 10; 7]
As already mentioned, you should pay attention to F# compiler warnings. Incomplete pattern matches even show you the sample of input which is not covered by the patterns. In your case it's (1,[]). When you insert value only once, your code will break when the source list is empty. But when you want to insert value recursively many times, checking for empty list is very important, because it's a base case to short-circuit recursion.
Another thing you should consider when inserting value recursively many times is resetting the number of items you want to skip before inserting value again. You cannot do that if you don't store original value of i somewhere. You can introduce the 4th parameter to the function (insert v i i l), but a better solution is to use wrapper function which is not recursive. Wrapper function will capture both initial i value, and v which should be inserted. Note that captured values visible to inner recursive function
let insert v i l = // non-recursive wrapper function
let rec skipAndInsert skip list =
match skip, list with
| _, [] -> [] // short-circuit recursion when there is no items left
| 0, _ -> v::skipAndInsert i list // nothing to skip, insert value and reset skip
| _, head::tail -> head::skipAndInsert (skip - 1) tail
skipAndInsert i l
insert 7 2 [1..10] |> printfn "%A" // [1; 2; 3; 7; 4; 5; 6; 7; 7; 8; 9; 7; 10]
Something like this can be used, when starting from your original code:
let insert v i l =
let rec insert2 v i p l =
match i, l with
| _, [] -> [v]
| 0, xs -> v::(insert2 v p p xs)
| i, x::xs -> x::insert2 v (i - 1) p xs
insert2 v i i l
First, your original code had a Incomplete pattern matches warning. In F# it's important to fix the warnings, because they almost always refer to a regular case that would cause your code to fail. In case of your function it would be failing if you call it on empty list: insert 1 1 []
To handle the case you described it's enough to repeat the insertion of a value at position i again, when position is back to 0. And the end of recursion is when the list becomes empty. I introduced p variable to keep the original position at which you want to insert element. For that I introduced a private function insert2, just to keep the insert method signature unchanged.
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.
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.
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]
I am working on a OCaml motion detection program. It analyzes two images and detects if there was motion. One part requires me summing a row of values and then also summing an entire image. This is what I have currenly:
let rec sumImRow(maskedrow) =
match maskedrow with
| [] -> 0
| mskRhd::mskRtl -> mskRhd + (sumImRow mskRtl)
;;
let rec sumImage(maskedimage) =
match maskedimage with
| mskRhd::mskRtl -> (sumImRow mskRhd)::(sumImage mskRtl)
| _ -> []
;;
and the given value is int list list -> int list = <fun>.
I don't quite understand why this is giving me int list.
tl;dr: You construct a new list instead of summing the integers.
Well, we can agree that sumImRow has type int list -> int as it takes elements from the list and then return their sum.
sumImage will have a list argument as it deconstructs it in the pattern matching. It then returns the list of result of sumImRow, meaning sumImage gets as argument a list of what sumImRow takes and returns a list of results. So we indeed have int list list -> int list.
You can avoid that by replacing :: with + and [] with 0 in sumImage's matching result.
You can also make a more improved code by using List.fold_left:
let sumImRow l = List.fold_left (+) 0 l;;
let sumImage l = List.fold_left (List.fold_left (+)) 0 l;;
The two return values of sumImage are both lists. So naturally its return type is a list.
(Most likely you should be using + rather than :: in sumImage. And the base case should be 0 rather than [].)
I wrote a recursive version of index as follows
let index list value =
let rec counter num = function
| [] -> -1
| h::t ->
if h == value
then num
else (counter (num + 1)) t
in counter 0 list;;
It works, but then our professor said we should use a tail recursive version in order to not timeout on the server, so I wrote a new index function using fold, but I can't seem to figure out why if it doesn't find the element, it returns a number greater than the length of the list, even though I want it to return -1.
let index2 list value = fold (fun i v ->
if i > (length list) then -1
else if v == value then i
else i+1) 0 list;;
Here's my fold version as well:
let rec fold f a l = match l with
[] -> a
| (h::t) -> fold f (f a h) t;;
Your folded function is called once for each element of the list. So you'll never see a value of i that's greater than (length list - 1).
As a side comment, it's quite inefficient (quadratic complexity) to keep calculating the length of the list. It would be better to calculate it once at the beginning.
As another side comment, you almost never want to use the == operator. Use the = operator instead.
EDIT
Why do you redefine fold instead of using List.fold_left?
Your first version of index is already tail recursive, but you can improve its style by:
using option type instead of returning -1 if not found;
directly call index recursively instead of a count function;
use = (structural) comparator instead of == (physical);
use a guard in your pattern matching instead of an if statement.
So
let index list value =
let rec index' list value i = match list with
| [] -> None
| h :: _ when h = value -> Some i
| _ :: t -> index' t value (succ i)
in index' list value 0
And as already said, index2 does not work because you'll never reach an element whose index is greater than the length of the list, so you just have to replace i > (length list) with i = (length list) - 1 to make it work.
But index2 is less efficient than index because index stops as soon as the element is found whereas index2 always evaluate each element of the list and compare the list length to the counter each time.