I am trying to figure out is there anyway that i can use append to make the three lists of integer inside a list to become a list of a list of integers, for example
[[1];[2];[3]] -> [[1;2;3]]
[] -> [[]]
[[]] -> []
but i am not sure how loop really in OCaml.
and the below is what i have tried, but i dont think it work
let rec ls (l : 'a list list) =
match l with
| [] -> []
| x :: y -> l#y
i have tried to use # to do function, but i don't how to remove the bracket.
Note that in your attempt, you never use x which is the head of the list, and the function is not recursive. It never calls itself. Note that # is never necessary in this exercise, which is good because it leads to some ugly performance implications.
Consider that you can use pattern-matching to identify whether a list is empty or not, and to extract elements from the head and the tail of a list. What should the result of flattening an empty list be? An empty list.
let rec flatten =
function
| [] -> []
Now, if the first list in the list of lists is empty, it should be the result of flattening the tail. This seems pretty obvious so far.
let rec flatten =
function
| [] -> []
| []::tl -> flatten tl
Now, if it's not empty then we can cons the first element of the first list onto the result of flattening... I'll leave that as an exercise for you to fill in.
let rec flatten =
function
| [] -> []
| []::tl -> flatten tl
| (x::xs)::tl -> x :: flatten ...
Looping via recursion
While OCaml does have imperative loops, it is much more idiomatic, especially when dealing with lists, to loop via recursion.
In order to use recursion to loop, there must be at least one exit case where the function does not recursively call itself, but there must also be at least one case where it does, and that function call must in some way update the state being passed in so that it converges on the exit case.
If the exit case is passing in an empty list, the recursive calls must get closer to passing in an empty list on each call or the recursion will never end.
If you did want to append...
If you decided you do like #, and don't care about O(n^2) runtime complexity, you can use it with List.fold_left to readily accomplish this goal.
# List.fold_left (#) [] [[1;2]; [3;4]];;
- : int list = [1; 2; 3; 4]
This is equivalent to [] # [1;2] # [3;4].
Related
I've written a function which search through a list of int-list to return the index of the list with an specific length by using pattern-matching:
let rec search x lst i = match lst with
| [] -> raise(Failure "Not found")
| hd :: tl -> if (List.length hd = x) then i else search x tl (i+1)
;;
For example:
utop # search 2 [ [1;2];[1;2;3] ] 0 ;;
- : int = 0
Is there a way to write a function with the same functionality using fold.left ?
What does List.fold_left actually do?
It takes (in reverse order to the order of arguments) a list, an initial value, and a function that works on that initial value and the first element in the list. If the list is empty, it returns the initial value. Otherwise it uses the function to update the initial value by way of recursion and works on the tail of the list.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
Now, what information do you need to keep track of as you iterate? The index. Easy enough.
But, what if you don't actually find a list of that length? You need to keep track of whether you've found one. So let's say we use a tuple of the index and a boolean flag.
Your function you pass to fold_left just needs to determine if a match has been found no update is necessary. Essentially we just no-op over the rest of the list. But, if we haven't found a match, then we need to test the current sublist's length and update the init value accordingly.
#glennsl (in a comment) and #Chris already explained that you may use List.fold_left but that it’s not the right tool for the job, because it processes the whole list whereas you want to stop once an occurrence is found. There are solutions but they are not satisfying:
(#Chris’ solution:) use a folding function that ignores the new elements once an occurrence has been found: you’re just wasting time, walking through the remaining tail for nothing;
evade the loop by throwing and catching an exception: better but hacky, you’re working around the normal functioning of List.fold_left.
I just mention that there is a generic function in the standard library that matches your situation almost perfectly:
val find : ('a -> bool) -> 'a list -> 'a
find f l returns the first element of the list l that satisfies the predicate f.
Raises Not_found if there is no value that satisfies f in the list l.
However it does not return the index, unlike what you are asking for. This is a deliberate design choice in the standard library, because list indexing is inefficient (linear time) and you shouldn’t do it. If, after these cautionary words, you still want the index, it is easy to write a generic function find_with_index.
Another remark on your code: you can avoid computing the lengths of inner lists fully, thanks to the following standard function:
val compare_length_with : 'a list -> int -> int
Compare the length of a list to an integer. compare_length_with l len is equivalent to compare (length l) len, except that the computation stops after at most len iterations on the list.
Since 4.05.0
So instead of if List.length hd = x, you can do if List.compare_length_with hd x = 0.
I'm trying to pattern match on a list of pairs, where I'm trying to return a list from the list of pair, however I'm having trouble figuring out where to make the recursive call. Without the recursive call I have this:
let countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]
;;
But naturally this only applies to the first pair in the list and simply returns ["countryA"; "countryB"] without the rest of the list.
With the recursive call this simply only returns an empty list:
let rec countriesInChart (cht: chart) =
match cht with
| [] -> []
| (x,y)::tt -> [x;y]::countriesInChart tt
;;
How would I make the recursive call such that all the pairs in the list would return as a list?
You have this:
[x;y] :: countriesInChart tt
This says to add a new list of two elements onto the front of a list of lists.
I don't think you want a list of lists, you just want a list. So you shouldn't be making a list of two elements.
If x and y are the same type (as I suspect they are), what you probably want is this:
x :: y :: countriesInChart tt
This says to add both x and y individually to the front of the recursively generated list.
You can also write this, which is completely equivalent:
[x; y] # countriesInChart tt
However, this constructs a list of two elements only to throw it away. So it's a tiny bit of extra work for no benefit.
I am to use combinators and no for/while loops, recursion or defined library functions from F#'s List module, except constructors :: and []
Ideally I want to implement map
I am trying to write a function called llength that returns the list of the lengths of the sublists. For example llength [[1;2;3];[1;2];[1;2;3]] should return [3;2,3]. I also have function length that returns the length of a list.
let Tuple f = fun a b -> f (a, b)
let length l : int =
List.fold (Tuple (fst >> (+) 1)) 0 l
currently have
let llength l : int list =
List.map (length inner list) list
Not sure how I should try accessing my sublists with my restraints and should I use my other method on each sublist? any help is greatly appreciated, thanks!
Since this is homework, I don't want to just give you a fully coded solution, but here are some hints:
First, since fold is allowed you could implement map via fold. The folding function would take the list accumulated "so far" and prepend the next element transformed with mapping function. The result will come out reversed though (fold traverses forward, but you prepend at every step), so perhaps that wouldn't work for you if you're not allowed List.rev.
Second - the most obvious, fundamental way: naked recursion. Here's the way to think about it: (1) when the argument is an empty list, result should be an empty list; (2) when the argument is a non-empty list, the result should be length of the argument's head prepended to the list of lengths of the argument's tail, which can be calculated recursively. Try to write that down in F#, and there will be your solution.
Since you can use some functions that basically have a loop (fold, filter ...), there might be some "cheated & dirty" ways to implement map. For example, via filter:
let mymap f xs =
let mutable result = []
xs
|> List.filter (fun x ->
result <- f x :: result
true)
|> ignore
result |> List.rev
Note that List.rev is required as explained in the other answer.
I'm learning about the map and fold functions. I'm trying to write a function that takes a list and returns a list with all of the values in the original, each followed by that value's double.
Example: add_dbls [2;5;8] = [2;4;5;10;8;16]
Everything I try results in a list of lists, instead of a list. I'm struggling to come up with a better approach, using either map or fold (or both).
This is what I came up with originally. I understand why this returns a list of lists, but can't figure out how to fix it. Any ideas would be appreciated!
let add_dbls list =
match list with
| h::t -> map (fun a-> [a;(a*2)]) list
| [] -> []
Also, my map function:
let rec map f list =
match list with
| h::t -> (f h)::(map f t)
| [] -> []
You are nearly there. As you have observed, since we get list of lists, we need to flatten it to get a final list. List.concat function does exactly that:
let add_dbls list =
let l =
match list with
| h::t -> List.map (fun a -> [a;(a*2)]) list
| [] -> []
in
List.concat l
Here is the updated function that that computes the output that you require.
Now the output of add_dbls [2;5;8] = [2;4;5;10;8;16].
Although this works, it probably isn't efficient as it allocates a new list per item in your original list. Below are variations of the same function with different characteristics which depend on the size of l.
(* Safe version - no stack overflow exception. Less efficient(time and size) than add_dbls3 below. *)
let add_dbls2 l =
List.fold_left
(fun acc a -> (a*2)::a::acc)
[]
l
|> List.rev
(* Fastest but unsafe - stack overflow exception possible if 'l' is large - fold_right is not tail-recursive. *)
let add_dbls3 l =
List.fold_right
(fun a acc -> a::(a*2)::acc)
l
[]
It's should be simple to see that List.map always returns a list of the same length as the input list. But you want a list that's twice as long. So List.map cannot work for you.
You can solve this using List.fold_left or List.fold_right. If you're still having trouble after you switch to using a fold, you could update your question with the new information.
Update
The type of your fold function (a left fold) is this:
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
So, the folded function takes an accumulated answer and an element of the list, and it returns a new accumulated answer.
Your folded function is like this:
fun a b -> a::b::(b*2)
It attempts to use the :: operator to add new elements to the end of the accumulated list. But that's not what the :: operator does. It adds an element to the beginning of a list.
There's no particularly nice way to add an element to the end of a list. This is intentional, because it's a slow operation.
When using a left fold, you need to reconcile yourself to building up the result in reverse order and possibly reversing it at the end. Or you can use a right fold (which is generally not tail recursive).
I have a F# function:
let removeEven (listToGoUnder : _ list) =
let rec listRec list x =
match list with
| [] -> []
| head::tail when (x%2 = 0) -> head :: listRec (tail) (x+1)
| head::tail -> listRec (tail) (x+1)
listRec listToGoUnder 0
It removes all elements at an even index in a list.
It works if I give the list some imput, like removeEven ['1';'2';'3'] I get ['1';'3'] which I am supposed to. But when I insert a empty list as parameter, I get this error:
stdin(78,1): error FS0030: Value restriction. The value 'it' has been
inferred to have generic type
val it : '_a list Either define 'it' as a simple data term, make
it a function with explicit arguments or, if you do not intend for it
to be generic, add a type annotation.
Help, anybody?
The empty list ([]) is quite special; it can be a list of any type. Therefore, the compiler complains that you don't have a specific type for []. Adding type annotation on the argument helps to solve the problem:
let results = removeEven ([]: int list)
or more idiomatic type annotation as suggested by #kvb:
let results: int list = removeEven []
This is probably beyond the question, but your function should be named as removeOdd since indices often start from 0 and your function removes all elements with odd indices. Moreover, things are much more clear if you use pattern matching on first two elements of the list rather than keep a counter x for checking indices:
let rec removeOdd = function
| [] -> []
| [x] -> [x]
| x::_::xs -> x::removeOdd xs