List Recursion in Ocaml - recursion

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.

Related

F# adding lists

How would I go about adding sub-lists.
For example, [ [10;2;10]; [10;50;10]] ----> [20;52;20] that is 10+10, 2+50 and 10+10. Not sure how to start this.
Fold is a higher order function:
let input = [[10;2;10]; [10;50;10]]
input |> Seq.fold (fun acc elem -> acc + (List.nth elem 1)) 0
val it : int = 52
Solution 1: Recursive version
We need a helper function to add two lists by summing elements one-to-one. It is recursive and assumes that both lists are of the same length:
let rec sum2Lists (l1:List<int>) (l2:List<int>) =
match (l1,l2) with
| ([],[]) -> []
| (x1::t1, x2::t2) -> (x1+x2)::sum2Lists t1 t2
Then the following recursive function can process a list of lists, using our helper function :
let rec sumLists xs =
match xs with
| [] -> [] // empty list
| x1::[] -> x1 // a single sublist
| xh::xt -> sum2Lists xh (sumLists xt) // add the head to recursion on tail
let myres = sumLists mylist
Solution 2: higher order function
Our helper function can be simplified, using List.map2:
let sum2hfLists (l1:List<int>) (l2:List<int>) = List.map2 (+) l1 l2
We can then use List.fold to create an on the flow accumulator using our helper function:
let sumhfList (l:List<List<int>>) =
match l with
| [] -> [] // empty list of sublist
| h::[] -> h // list with a single sublist
| h::t -> List.fold (fun a x -> sum2hfLists a x) h t
The last match case is applied only for lists of at least two sublists. The trick is to take the first sublist as starting point of the accumulator, and let fold execute on the rest of the list.

F# Split Function

I'm building a merge sort function and my split method is giving me a value restriction error. I'm using 2 accumulating parameters, the 2 lists resulting from the split, that I package into a tuple in the end for the return. However I'm getting a value restriction error and I can't figure out what the problem is. Does anyone have any ideas?
let split lst =
let a = []
let b = []
let ctr = 0
let rec helper (lst,l1,l2,ctr) =
match lst with
| [] -> []
| x::xs -> if ctr%2 = 0 then helper(xs, x::l1, l2, ctr+1)
else
helper(xs, l1, x::l2, ctr+1)
helper (lst, a, b, ctr)
(a,b)
Any input is appreciated.
The code, as you have written it, doesn't really make sense. F# uses immutable values by default, therefore your function, as it's currently written, can be simplified to this:
let split lst =
let a = []
let b = []
(a,b)
This is probably not what you want. In fact, due to immutable bindings, there is no value in predeclaring a, b and ctr.
Here is a recursive function that will do the trick:
let split lst =
let rec helper lst l1 l2 ctr =
match lst with
| [] -> l1, l2 // return accumulated lists
| x::xs ->
if ctr%2 = 0 then
helper xs (x::l1) l2 (ctr+1) // prepend x to list 1 and increment
else
helper xs l1 (x::l2) (ctr+1) // prepend x to list 2 and increment
helper lst [] [] 0
Instead of using a recursive function, you could also solve this problem using List.fold, fold is a higher order function which generalises the accumulation process that we described explicitly in the recursive function above.
This approach is a bit more concise but very likely less familiar to someone new to functional programming, so I've tried to describe this process in more detail.
let split2 lst =
/// Take a running total of each list and a index*value and return a new
/// pair of lists with the supplied value prepended to the correct list
let splitFolder (l1, l2) (i, x) =
match i % 2 = 0 with
|true -> x :: l1, l2 // return list 1 with x prepended and list2
|false -> l1, x :: l2 // return list 1 and list 2 with x prepended
lst
|> List.mapi (fun i x -> i, x) // map list of values to list of index*values
|> List.fold (splitFolder) ([],[]) // fold over the list using the splitFolder function

Map a list of options to list of strings

I have the following function in OCaml:
let get_all_parents lst =
List.map (fun (name,opt) -> opt) lst
That maps my big list with (name, opt) to just a list of opt. An option can contain of either None or Some value which in this case is a string. I want a list of strings with all my values.
I am a beginner learning OCaml.
I don't think filter and map used together is a good solution to this problem. This is because when you apply map to convert your string option to string, you will have the None case to deal with. Even if you know that you won't have any Nones because you filtered them away, the type checker doesn't, and can't help you. If you have non-exhaustive pattern match warnings enabled, you will get them, or you will have to supply some kind of dummy string for the None case. And, you will have to hope you don't introduce errors when refactoring later, or else write test cases or do more code review.
Instead, you need a function filter_map : ('a -> 'b option) -> 'a list -> 'b list. The idea is that this works like map, except filter_map f lst drops each element of lst for which f evaluates to None. If f evaluates to Some v, the result list will have v. You could then use filter_map like so:
filter_map (fun (_, opt) -> opt) lst
You could also write that as
filter_map snd lst
A more general example would be:
filter_map (fun (_, opt) ->
match opt with
| Some s -> Some (s ^ "\n")
| None -> None)
lst
filter_map can be implemented like this:
let filter_map f lst =
let rec loop acc = function
| [] -> List.rev acc
| v::lst' ->
match f v with
| None -> loop acc lst'
| Some v' -> loop (v'::acc) lst'
in
loop [] lst
EDIT For greater completeness, you could also do
let filter_map f lst =
List.fold_left (fun acc v ->
match f v with
| Some v' -> v'::acc
| None -> acc) [] lst
|> List.rev
It's a shame that this kind of function isn't in the standard library. It's present in both Batteries Included and Jane Street Core.
I'm going to expand on #Carsten's answer. He is pointing you the right direction.
It's not clear what question you're asking. For example, I'm not sure why you're telling us about your function get_all_parents. Possibly this function was your attempt to get the answer you want, and that it's not quite working for you. Or maybe you're happy with this function, but you want to do some further processing on its results?
Either way, List.map can't do the whole job because it always returns a list of the same length as its input. But you need a list that can be different lengths, depending on how many None values there are in the big list.
So you need a function that can extract only the parts of a list that you're interested in. As #Carsten says, the key function for this is List.filter.
Some combination of map and filter will definitely do what you want. Or you can just use fold, which has the power of both map and filter. Or you can write your own recursive function that does all the work.
Update
Maybe your problem is in extracting the string from a string option. The "nice" way to do this is to provide a default value to use when the option is None:
let get default xo =
match xo with
| None -> default
| Some x -> x
# get "none" (Some "abc");;
- : string = "abc"
# get "none" None;;
- : string = "none"
#
type opt = Some of string | None
List.fold_left (fun lres -> function
(name,Some value) -> value::lres
| (name,None) -> lres
) [] [("s1",None);("s2",Some "s2bis")]
result:
- : string list = ["s2bis"]

Return index of an asked-for value of a list using fold in OCaml

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.

Set Intersection with Tail Recursion

I am trying to produce the solution for an intersection of two sets using tail recursion and an empty list [] as an accu:
let rec setintersect list list =
let rec setintersect2 a b c =
match a with
| [] -> (match b with [] -> (setsimplify c) | h::t -> (setsimplify c))
| h1::t1 -> (match b with [] -> (setsimplify c) |h2::t2 -> (if (elementof h1 b) then (setintersect2 t1 b (c#[h1])) else (setintersect2 t1 b c))) in
setintersect2 list list [];;
Elementof takes takes "an int and a list" and is correctly working to give true if x is an element of the list, false otherwise..
Here is the problem:
# setintersect [5;2;1] [2;6;9];;
- : int list = [2; 6; 9]
and it should give [2].
What am I doing wrong?
I feel like there's something really simple that I am misunderstanding!
Edit:
Thanks for the responses so far.
setsimplify just removes the duplicates.
so [2,2,3,5,6,6] becomes [2,3,5,6]. Tested and made sure it is working properly.
I am not supposed to use anything from the List library either. Also, I must use "tail recursion" with the accumulator being a list that I build as I go.
Here is the thought:
Check the head element in list1, IF it exists in list2, THEN recurse with the "tail of list1, list2, and list c with that element added to it". ELSE, then recurse with "tail of list1, list2 and list c(as it is)".
end conditions are either list1 or list2 are empty or both together are empty, return list c (as it is).
let rec setintersect list list = is wrong: the two arguments should be named differently (you should of course update the call to setintersect2 accordingly), otherwise the second will shadow the first. I would have thought that OCaml would have at least warned you about this fact, but it appears that it is not the case.
Apart from that, the code seems to do the trick. There are a couple of things that could be improved though:
setintersect itself is not recursive (only setintersect2 is), you thus don't need the rec
you should find a different name for the argument of setintersect2. In particular, it is not obvious which is the accumulator (acc or accu will be understood by most OCaml programmers in these circumstances).
c#[h1] is inefficient: you will traverse c completely each time you append an element. It's better to do h1::c and reverse the result at the end
As a bonus point, if you append element at the beginning of c, and assume that a is ordered, you don't have to call setsimplify at the end of the call: just check whether c is empty, and if this is not the case, append h1 only if it is not equal to the head of c.
First, You didn't list out your setsimplify function.
To write an ocaml function, try to split it first, and then combine if possible.
To solve this task, you just go through all elements in l1, and for every element, you check whether it is in l2 or not, right?
So definitely you need a function to check whether an element is in a list or not, right?
let make one:
let rec mem x = function
| [] -> false
| hd::tl -> hd = x || mem x tl
Then you can do your intersection:
let rec inter l1 l2 =
match l1 with
| [] -> []
| hd::tl -> if mem hd l2 then hd::(inter tl l2) else inter tl l2
Note that the above function is not tail-recursive, I guess you can change it to tail-recursive as an excise.
If you use std library, then it is simple:
let intersection l1 l2 = List.filter (fun x -> List.mem x l2) l1

Resources