So here is what I have so far. It feels close but im not sure how to fix the problems in line 84 (2nd to last line: elif List.append(isolate(a),isolate(b)) != [] then List.append(isolate(a),isolate(b))).
(* val isolate : l:'a list -> 'a list when 'a : equality *)
let rec isolate (l:'a list) =
match l with
| [] -> []
| x::xs ->
if memberof(x,xs)
then
let xs = remove (x,l)
isolate xs
else isolate xs
( * val common : 'a list * 'a list -> 'a list when 'a : equality *)
let rec common (k: 'a list, l:'a list) =
match ((k:'a list),(l:'a list)) with
| (a, b) ->
if a=[] then []
elif b=[] then []
elif List.append(isolate(a),isolate(b)) != [] then List.append(isolate(a),isolate(b))
else []
edit:
asked to post whole code:
(* val sumlist : l:float list -> float *)
let rec sumlist l =
match (l:float list) with
| [] -> 0.0
| a::x -> (sumlist x) + a
(* :: creates a list. *)
sumlist([1.0;2.0;3.0])
(* val squarelist : l:float list -> float list *)
let rec squarelist l =
match (l:float list) with
| [] -> []
| a::x -> (a*a)::(squarelist x)
(* val mean : l:float list -> float *)
let mean l =
match (l:float list) with
| [] -> 0.0
| l -> (sumlist l)/(float)l.Length
mean([1.0;2.0;3.0])
(* val mean_diffs : l:float list -> float list *)
let mean_diffs l =
match l with
set a = mean(l)
| [] -> []
let rec diffs (a,l)=
match l with
| x::xs -> (x-(mean(l))::diffs(xs)
| [] -> l
mean_diffs([1.0;2.0;3.0])
(* val variance : l:float list -> float *)
let variance l =
match (l:float list) with
| [] -> 0.0
| l -> (sumlist (squarelist (mean_diffs l)))/(float)l.Length
(* End of question 1 *) (* Do not edit this line. *)
(* Question 2 *) (* Do not edit this line. *)
(* val memberof : 'a * 'a list -> bool when 'a : equality *)
let rec memberof l=
match (l: 'a * 'a list) with
| (t,[]) -> false
| (t, x::xs) when t=x -> true
| (t, x::xs) -> t=x || memberof(t,xs)
(* val remove : 'a * 'a list -> 'a list when 'a : equality *)
let rec remove ((k:'a),(l:'a list)) =
match l with
| [] -> []
| x::xs when x=k -> xs
| x::xs ->x::(remove(k,xs))
(* End of question 2 *) (* Do not edit this line *)
(* Question 3 *) (* Do not edit this line *)
(* val isolate : l:'a list -> 'a list when 'a : equality *)
let rec isolate (l:'a list) =
match l with
| [] -> []
| x::xs ->
if memberof(x,xs)
then
let xs = remove (x,l)
isolate xs
else isolate xs
(* End of question 3 *) (* Do not edit this line *)
(* Question 4 *) (* Do not edit this line *)
(* val common : 'a list * 'a list -> 'a list when 'a : equality *)
let rec common (k: 'a list, l:'a list) =
match ((k:'a list),(l:'a list)) with
| (a, b) ->
if a=[] then []
elif b=[] then []
elif List.append(isolate(a),isolate(b)) <> [] then List.append(isolate(a),isolate(b))
else []
common([1.0;2.0;6.0;10.0],[5.0;6.0;10.0])
It seems that <> has fixed the problem but do you have any advice on my function mean_diffs?
Since this appears that you are working on a course and it is building upon the previous exercises, the code is converted to more F# idiomatic and a standardized format of recursive functions to make them easier to use when you get to currying See: F# for fun and profit and Functions as First-Class Values (F#) and other more advanced concepts.
The format is basically
let funXYZ list =
let rec funXYZInner list acc =
match list with
| head :: tail ->
let acc = (somefunc head) :: acc
funXYZInner tail acc
| [] -> acc
funXYZInner list []
where funXYZ is an exposed function name that does NOT have a rec. I can't recall the source but if you can implement a function needing a rec with the rec not being exposed it makes the code more portable.
The basic concept is that you take a list and pull the list apart into a head and tail:
head :: tail
then you process the head:
somefunc head
then accumulate the result into the accumulator
let acc = value :: acc
let acc = value + acc
let acc = acc + (value * value)
then process the remainder of the list, e.g. tail, passing the accumulator
funXYZInner tail acc
When the input list matches empty
| []
just return the result which was accumulated in the accumulator
acc
The inner function funXYZInner does have a rec and uses an accumulator, i.e. acc. This will help in understanding how to use tail calls which will keep you from running out of memory on large computations.
You probably know already that with match statements you want to cover all of the cases of the match variable. This is because of algebraic data types and is the reason you see those warnings about not all cases being covered. If you see one of those warnings and don't know why you are getting it you need to fix them, or run the risk of unexpected runtime errors or crashes.
While the code you gave can only work with float type list, in the future to make it work with more types you will need to learn about LanguagePrimitives.GenericZero<^T> Type Function (F#).
There are some more basic functions that were added because they were needed, e.g. reverse, and help to show the progression as the examples get more complex.
Do to the fact that examples build upon themselves and you had a specific error in the last one, it was better to give the examples a better foundation which should mitigate common problems encountered when first learning about recursive functions.
With regards to the accumulator, the accumulator can hold different types, e.g. float, list, int, and there can be more than one accumulator being used in the recursive function, e.g. numeratorAcc, denominatorAcc. Also by pulling out the calculation of the accumulator value, e.g.let acc = ..., when you get to more advanced functions you can just pass in a function to replace that calculation.
There is one predicate function memberof which does not use an accumulator. A predicate is a function that returns true or false, and once you reach the desired value you can stop processing the remainder of the list.
Also of note is that while some of the functions could call earlier defined functions, the examples don't make the calls so that they can process the list in one pass. When functions call other functions with list, each function has to process the entire list to return the result. By using rec functions it is sometimes possible to process the list once by doing multiple calculations with the head. However there are times this cannot be done. I did not maximize the functions one way or the other but left them a way that give more variation for learning. Feel free to rewrite them which will lead to function composition.
You will probably have more questions about these examples, so please ask as separate SO questions instead of building on this one.
All the code
// val reverse : l:'a list -> 'a list
let reverse l =
let rec reverseInner l acc =
match l with
| x::xs ->
let acc = x :: acc
reverseInner xs acc
| [] -> acc
reverseInner l []
reverse [ 3.0; 2.0; 1.0 ] // val it : float list = [1.0; 2.0; 3.0]
// val length : l:'a list -> int
let length l =
let rec lengthInner l acc =
match l with
| x::xs ->
let acc = acc + 1
lengthInner xs acc
| [] -> acc
lengthInner l 0
length [ 3.0; 2.0; 1.0 ] // val it : int = 3
// val sum : l:float list -> float
let sum l =
let rec sumInner l acc =
match l with
| x::xs ->
let acc = acc + x
sumInner xs acc
| [] -> acc
sumInner l 0.0
sum [ 1.0; 2.0; 3.0 ] // val it : float = 6.0
// val square : l:float list -> float list
let square (l : float list) =
let rec squareInner l acc =
match l with
| x::xs ->
let acc = (x * x) :: acc
squareInner xs acc
| [] -> reverse acc
squareInner l []
square [ 1.0; 2.0; 3.0 ] // val it : float list = [1.0; 4.0; 9.0]
// val mean : l:float list -> float
let mean l =
let rec meanInner l sumacc lengthacc =
match l with
| x::xs ->
let sumacc = sumacc + x
let lengthacc = lengthacc + 1.0
meanInner xs sumacc lengthacc
| [] -> sumacc / lengthacc
meanInner l 0.0 0.0
mean([1.0;2.0;3.0]) // val it : float = 2.0
// val mean_diffs : l:float list -> float list
let meanDiff l =
let rec meanDiffInner l m acc =
match l with
| x::xs ->
let diff = (x - m)
let acc = diff :: acc
meanDiffInner xs m acc
| [] -> reverse acc
meanDiffInner l (mean l) []
meanDiff [ 1.0; 2.0; 3.0 ] // val it : float list = [-1.0; 0.0; 1.0]
// From: https://en.wikipedia.org/wiki/Variance
// Suppose a population of numbers consists of 3, 4, 7, and 10.
// The arithmetic mean of these numbers, often informally called the "average", is (3+4+7+10)÷4 = 6.
// The variance of these four numbers is the average squared deviation from this average.
// These deviations are (3–6) = –3, (4–6) = –2, (7–6) = 1, and (10–6) = 4.
// Thus the variance of the four numbers is ((-3)^2 + (-2)^2 + (1)^2 + (4)^2) / 4 = 15/2 = 7.5
// val variance : l:float list -> float
let variance l =
let deviations = meanDiff l
let rec varianceInner l numeratorAcc denomenatorAcc =
match l with
| devation::xs ->
let numeratorAcc = numeratorAcc + (devation * devation)
let denomenatorAcc = denomenatorAcc + 1.0
varianceInner xs numeratorAcc denomenatorAcc
| [] -> numeratorAcc / denomenatorAcc
varianceInner deviations 0.0 0.0
variance [ 1.0; 2.0; 3.0 ] // val it : float = 0.6666666667
variance [ 3.0; 4.0; 7.0; 10.0 ] // val it : float = 7.5
(* End of question 1 *) (* Do not edit this line. *)
(* Question 2 *) (* Do not edit this line. *)
// val memberof : l:'a list -> item:'a -> bool when 'a : equality
let memberof l item =
let rec memberInner l item =
match l with
| x::xs ->
if x = item then
true
else
memberInner xs item
| [] -> false
memberInner l item
memberof [ 1.0; 2.0; 3.0 ] 0.0 // val it : bool = false
memberof [ 1.0; 2.0; 3.0 ] 1.0 // val it : bool = true
memberof [ 1.0; 2.0; 3.0 ] 2.0 // trueval it : bool = true
memberof [ 1.0; 2.0; 3.0 ] 3.0 // val it : bool = true
memberof [ 1.0; 2.0; 3.0 ] 4.0 // val it : bool = false
// val remove : l:'a list -> item:'a -> 'a list when 'a : equality
let remove l item =
let rec removeInner l item acc =
match l with
| x::xs ->
if x = item then
removeInner xs item acc
else
let acc = x :: acc
removeInner xs item acc
| [] -> reverse acc
removeInner l item []
remove [ 1.0; 2.0; 3.0 ] 0.0 // val it : float list = [1.0; 2.0; 3.0]
remove [ 1.0; 2.0; 3.0 ] 1.0 // val it : float list = [2.0; 3.0]
remove [ 1.0; 2.0; 3.0 ] 2.0 // val it : float list = [1.0; 3.0]
remove [ 1.0; 2.0; 3.0 ] 3.0 // val it : float list = [1.0; 2.0]
remove [ 1.0; 2.0; 3.0 ] 4.0 // val it : float list = [1.0; 2.0; 3.0]
(* End of question 2 *) (* Do not edit this line *)
(* Question 3 *) (* Do not edit this line *)
// val isolate : list:'a list -> 'a list when 'a : equality
let isolate list =
let rec isolateInner searchList commonlist =
match searchList with
| x::xs ->
if (memberof commonlist x) then
isolateInner xs commonlist
else
let commonlist = (x :: commonlist)
isolateInner xs commonlist
| [] -> reverse commonlist
isolateInner list []
isolate [ 1.0; 2.0; 3.0 ] // val it : float list = [1.0; 2.0; 3.0]
isolate [ 1.0; 1.0; 2.0; 3.0 ] // val it : float list = [1.0; 2.0; 3.0]
isolate [ 1.0; 2.0; 2.0; 3.0 ] // val it : float list = [1.0; 2.0; 3.0]
isolate [ 1.0; 2.0; 3.0; 3.0 ] // val it : float list = [1.0; 2.0; 3.0]
isolate [ 3.0; 2.0; 1.0; 1.0; 2.0; 3.0; 2.0; 1.0; 1.0; 3.0] // val it : float list = [3.0; 2.0; 1.0]
(* End of question 3 *) (* Do not edit this line *)
(* Question 4 *) (* Do not edit this line *)
// val common : a:'a list -> b:'a list -> 'a list when 'a : equality
let common a b =
let rec commonInner a b acc =
match (a,b) with
| (x::xs,b) ->
if (memberof acc x) then
commonInner xs b acc
else
let acc = x :: acc
commonInner xs b acc
| ([],y::ys) ->
if (memberof acc y) then
commonInner [] ys acc
else
let acc = y :: acc
commonInner [] ys acc
| ([],[]) -> reverse acc
commonInner a b []
common [ 1.0; 2.0; 6.0; 10.0] [ 5.0; 6.0; 10.0 ] // val it : float list = [1.0; 2.0; 6.0; 10.0; 5.0]
Related
How to create a tuple list from one single list, like so:
[1; 2; 4; 6] -> [(1, 2); (4, 6)]
I want to do it using function List.fold_left since I'm trying to learn that currently but don't know how... Is there a way? Or should I leave it like that?
This is a working code that doesn't use List.fold_left:
let rec create_tuple acc l = match l with
| [] -> acc
| x :: y :: l' -> create_tuple (acc # [(x, y)]) l'
| _ -> acc
List.fold_left reads elements one by one. There is no direct way to make it read elements two by two.
It really is pointless complication (great for teaching, though), but if you absolutely want to use List.fold_left here, your accumulator needs to somehow record the state of the traversal:
either you have read an even number of elements so far,
or you have read an odd number and then you have to record what was the last element you read, so that, upon reading the following one, you can pair them.
Here is a way to do it. I use an algebraic datatype to represent the state.
(* This is the type that we’ll use for the accumulator;
the option component is the state of the traversal.
(None, acc) means that we have read an even number of elements so far;
(Some x, acc) means that we have read an odd number of elements so far,
the last of which being x. *)
type 'a accumulator = 'a option * ('a * 'a) list
let folder (state, acc) x =
match state with
| None -> (Some x, acc)
| Some y -> (None, (y,x)::acc)
let create_pairs l =
let (_, acc) = List.fold_left folder (None, []) l in
List.rev acc
Also notice how I avoid the complexity bug that I outlined in a comment: I add elements in reverse order (i.e. at the head of the accumulating list), and at the very end I reverse that list.
#Maëlan's answer is beautiful, but what if we want to get triples rather than pairs? Is there a way we can use List.fold_left to handle this more generically?
let chunks n lst =
let (_, _, acc) = List.fold_left
(fun (counter, chunk, lst') x ->
if counter = n - 1 then
(0, [], List.rev (x :: chunk) :: lst')
else
(counter + 1, x :: chunk, lst'))
(0, [], [])
lst
in
List.rev acc
Using this, chunks 2 [1; 2; 4; 6] returns [[1; 2]; [4; 6]]. We can map this to the result you're looking for with a very simple function that takes a list with two elements and creates a tuple with two elements.
chunks 2 [1; 2; 4; 6] |> List.map (fun [x; y] -> (x, y))
And we get:
[(1, 2), (4, 6)]
This could be used to implement a triples function.
let create_triples lst =
chunks 3 lst |> List.map (fun [x; y; z] -> (x, y, z));;
And now create_triples [1; 2; 3; 4; 5; 6; 7; 8; 9] returns [(1, 2, 3); (4, 5, 6); (7, 8, 9)].
I tried this question(using List.fold_left) and this is the best I could come up with:
type 'a node = First of 'a | Second of ('a * 'a)
let ans =
List.fold_left
(
fun a e ->
match a with
| [] -> (First e)::a
| (First f)::tl -> Second(f, e)::tl
| (Second n)::tl -> (First e)::(Second n)::tl
)
[]
[1; 2; 3; 4; 5; 6; ]
let () =
List.iter
(
fun e ->
match e with
| First f ->
print_endline(string_of_int f)
| Second (f, s) ->
Printf.printf "(%d, %d)" f s
)
(List.rev ans)
Just to make my answer all there...
type 'a node = One of 'a | Two of ('a * 'a)
let ans =
(List.map
(
fun e ->
match e with
| One _ -> failwith "Should only be Two's"
| Two (f, s) -> (f, s)
)
(List.filter
(
fun e ->
match e with
| One _ -> false
| Two _ -> true
)
(List.rev
(List.fold_left
(
fun a e ->
match a with
| [] -> (One e)::[]
| (One o)::tl -> (Two (o, e))::tl
| (Two t)::tl -> (One e)::(Two t)::tl
)
[]
(List.init 10 (fun x -> x + 1))
)
)
)
)
let () =
List.iter
(fun (f, s) -> Printf.printf "(%d, %d) " f s)
ans
I’m trying to create a function that takes an int list as an argument and returns the sum of the product between an int and its position in the list. To put in an example this : multSum [5; 11; 15] should return (5 * 1 + 11 * 2 + 15 * 3) = 72.
It should be written recursively and I’m trying while avoiding List.map or List.filter or any other prefabricated functions.
By dividing and reigning the query above, I have so far started by trying the following :
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t ;;
val tir : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
then I moved to this :
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto";;
val carto : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
with the final idea to be able to do that :
let prod arg1 arg2 =
tir (+) 1 (carto ( * ) arg1 arg2);;
val prod : int list -> int list -> int = <fun>
But I am stuck now and I’m not sure of my orientation from here forward. I thought of trying to search for the index in a "l" and replace each index int in the acc, in order to make it work but I'm afraid I'm rather complicating things... Any help please ?
Edit 1 :
let rec multSum l =
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t)in
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t in
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto" in
let prod arg1 arg2 =
tir (+) 0 (carto ( * ) arg1 arg2) in
prod l (indices 1 l);;
val multSum : int list -> int = <fun>
Building on your replies, surely these are 'fold' and 'map' rewritten. At least, I'm sure now that I was on the right track. I have come to put together the whole code as signaled above in Edit 1.
It seems to be working well... I know that I want a recursive function and here it is. But, do you think it could be done even shorter recursively of course?
#coredump is quite right about this looking like an ideal scenario for a fold, but the extra functions aren't really that necessary. We can just use a tuple to pass the index and sum information around, then when we're done, discard the index information from the tuple.
let sum_list_prod lst =
let (_, result) = List.fold_left
(fun (i, sum) x -> (i + 1, sum + i * x))
(1, 0)
lst
in
result
Edit: A simple implementation of a left fold to demonstrate the recursion going on here.
let rec foldl f init lst =
match lst with
| [] -> init
| first :: rest -> foldl f (f init first) rest
So working through a simple example with sum_list_prod:
sum_list_prod [2; 3; 4]
Calls the fold like so:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
And as that evaluates:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (2, 2) [3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (3, 8) [4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (4, 20) []
(4, 20)
And then we throw away the 4 because we don't need it anymore and are just left with 20.
Your tir functions looks like a fold; in fact has the exact same type as List.fold_left:
# List.fold_left;;
- : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
In the following snippets the prod function looks like a map2
# List.map2;;
- : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
You can use a fold and a map to compute the function you want, but you also need first to build a list of indices from the list of values. You could do this as follows:
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t);;
For example:
# indices 1 [5;1;3];;
- : int list = [1; 2; 3]
This is not recursive terminal, if you first computed the length of the list, how would you build the list in a recursive terminal way?
Then you should be able to call prod on a list xs and on a secondary list indices 1 xs. It is a bit wasteful because you need to build an auxiliary list, but it looks quite simple to me to understand, higher-order functions like map or fold do work on whole lists so there are fewer corner cases to consider.
But, it might be better to first write a direct recursive function for your particular problem before going the more abstract route.
The direct recursive function also requires no additional memory allocation. If you write a recursive terminal function you'll carry additional accumulator values:
the current position in the list, initially 1
the current sum of products, initially 0
Then, your function has the following skeleton:
let rec f xs index product = match xs with
| [] -> ...
| h::t -> ...
You can wrap it in a main function g:
let g xs = f xs 1 0;;
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> *)
How can I write a function using fold_left and not using fold to count the number of elements in a list?
I tried
let rec count_elements l c =
match l with
|[] -> c
|h::t -> c = c+1
I don't believe this works, and I am not how to do this using fold_left, any guidance would be appreciated
To add some clarity to the answers, I'd like to stress some things :
fold_left is just a way of doing some operations on a list in a tail-recursive way. The best way to understand fold_left is to do your own implementation of it :
# let fold_left f acc l =
let rec fr acc l =
match l with
| [] -> acc
| hd :: tl -> fr (f acc hd) tl
in fr acc l;;
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
That's exactly what length does when you write
# let length l = List.fold_left (fun c _ -> c + 1) 0 l;;
val length : 'a list -> int = <fun>
What happens is equivalent to :
# let length l =
let rec lr acc l =
match l with
| [] -> acc
| _ :: tl -> lr (acc + 1) tl
in lr 0 l;;
val length : 'a list -> int = <fun>
So, the solution
let rec length l =
match l with
| [] -> 0
| _ :: tl -> 1 + length tl
corresponds to fold_right and is not tail-recursive.
Hoping this will clarify some things for you :-)
Using fold_left, you can do it like this :
# let size l = List.fold_left (fun acc _ -> acc + 1) 0 l;;
val size : 'a list -> int = <fun>
# size [1;2;3];;
- : int = 3
# size [];;
- : int = 0
#
You start with the accumulator 0 and then you add it +1 for every element in the list.
I'm trying to figure out how to code this.
Implement in F# a function that tests whether an element is a member of a given list. Here is the type I want.
val memberof : ’a * ’a list -> bool when ’a : equality
Here are examples of the function in action.
memberof 1 [1;2;3];;
error FS0003: This value is not a function and cannot be applied
memberof (1,[1;2;3]);;
val it : bool = true
memberof (1, []);;
val it : bool = false
memberof (1,[2;3;4]);;
val it : bool = false
heres what i've put together...
let rec memberof l =
match (l:float) with
| a.Item(l) -> l -> bool + (memberof l)
or
let rec memberof l =
match (l:float list) with
| [] -> false
| (a:float)::b -> (a)=(memberof b)->bool
let rec memberof (l : float list) (item : float) : bool =
match l with
| hd::tl when hd = item -> true
| hd::tl -> memberof tl item
| [] -> false
or
let rec memberof (l : float list) (item : float) : bool =
match l with
| hd::tl ->
if hd = item then
true
else
memberof tl item
| [] -> false
or
let rec memberof (l : float list) (item : float) : bool =
match l with
| [] -> false
| hd :: tl ->
hd = item
|| memberof tl item
Test cases
let test001 = memberof [1.0; 2.0; 3.0] 0.0
printfn "test001: %A" test001
let test002 = memberof [1.0; 2.0; 3.0] 1.0
printfn "test002: %A" test002
let test003 = memberof [1.0; 2.0; 3.0] 2.0
printfn "test003: %A" test003
let test004 = memberof [1.0; 2.0; 3.0] 3.0
printfn "test004: %A" test004
let test005 = memberof [] 0.0
printfn "test005: %A" test005
Which outputs
val test001 : bool = false
val test002 : bool = true
val test003 : bool = true
val test004 : bool = true
val test005 : bool = false
The problem with
let rec memberof l =
match (l:float list) with
| [] -> false
| (a:float)::b -> (a)=(memberof b)->bool
is that
| (a:float)::b -> (a)=(memberof b)->bool
is pulling the list apart correctly with
(a:float)::b
however
(a)=(memberof b)->bool
is not right.
With recursive functions over a list you want to pull off the head of the list and process the head. Then you want to call the function again, this time passing the tail of the list as the new list variable, e.g.
memberof tl item
Since this is a predicate, we only need to stop once we reach a desired true or false. In this example when true is found the function can end, so no need to call memberof for the remainder of the list.
For the particular signature you requested
val memberof : item:'a * list:'a list -> bool when 'a : equality
let rec memberof ((item : 'a), (list : 'a list)) : bool when 'T : equality =
match list with
| hd::tl ->
if hd = item then
true
else
memberof (item, tl)
| [] -> false