I have one task in hand that I am 90% done with it but just don't quite know how to finish it. So the task is as follows : " Write a non-recursive function which takes a function, and two lists as an input, and returns a third list which contains the result of the function applied on all possible pairs of elements from both input lists." So I have to get it as below.
# cart_fun ( * ) [1;2;2;6;3;9;1] [2;3];; -: int list = [2; 3; 4; 6; 4; 6; 12; 18; 6; 9; 18; 27; 2; 3]
My struggle is that I don't know how to make a function substitution. Here is my code.
let cart_fun list1 list2 =
let res = List.fold_left (fun acc x -> List.fold_left (fun acc y -> (x * y) :: acc) acc list2) [] list1
in List.rev res;;
But I would like that in part (x*y) the multiplication be given as an argument before the lists.
Thank you for your help in advance.
Most of the journey has already been made! Well done!
As you can see by using the fold_left function, in OCaml (as in other functional languages) you can pass functions as arguments (and even return them), which is why you can provide fold_left with an accumulation function. Here is your code:
let cart_fun list1 list2 =
let res = List.fold_left (fun acc x ->
List.fold_left (fun acc y -> (x * y) :: acc) acc list2)
[] list1
in List.rev res;;
Even if the code is very good, let's rephrase it a bit to see it more clearly!
let cart_fun list1 list2 =
let process_list_2 fst_acc =
List.fold_left
(fun snd_acc y -> (x * y) :: snd_acc)
fst_acc
list2
in
let result = List.fold_left (fun acc x -> process_list_2 acc x) [] list1 in
List.rev result
As you may have realised: (fun acc x -> process_list_2 acc x) is, in fact, identical to process_list_2 so, let's rephase one more time:
let cart_fun list1 list2 =
let process_list_2 fst_acc =
List.fold_left
(fun snd_acc y -> (x * y) :: snd_acc)
fst_acc
list2
in
let result = List.fold_left process_list_2 [] list1 in
List.rev result
But hey, we want to generalise cart_fun in ordrer to have, instead of cart_fun list1 list2, we want cart_fun modifier list1 list2, where modifier is just a function... So, no problem, let's changing this part of the code:
let cart_fun modifier list1 list2 =
let process_list_2 fst_acc =
List.fold_left
(fun snd_acc y -> (modifier x y) :: snd_acc)
fst_acc
list2
in
let result = List.fold_left process_list_2 [] list1 in
List.rev result
And voila! As you can see, there wasn't much modification required. Just keep in mind that in OCaml, you can consider that a variable will contain a function; which is pretty cool!
Btw, the "general behaviour" that you want to capture looks a lot like what we call "a comprehension" (like in Python and Haskell). And since OCaml 4.10, there is a function in list module which allow you to write easily comprehension : List.concat_map val concat_map : ('a -> 'b list) -> 'a list -> 'b list which has the same effect than mapping over a list of 'a, producing a list of list of b and flatten the list into a list of b.
So you can see your cartesian product as :
let cart_fun modifier list1 list2 =
List.concat_map (fun x ->
List.concat_map (fun y ->
[modifier x y]
) list2
) list1
But as you can see... it's not much more readable than before! Fortunately, in addition to passing functions as arguments, OCaml also allows you to describe your own operators. For example, here we could describe an operator to simplify the chaining of concat_map which we would randomely call... >>= :
let (>>=) list f = List.concat_map f list
let cart_fun modifier list1 list2 =
list1 >>= fun x ->
list2 >>= fun y -> [modifier x y]
Awesome, can we go deeper in the readability ? Of course, since OCaml 4.08, you can define let operators. So defining your own let with a suffix. For example, here, let's define let* (which will be exactly the same of >>=)
let (let*) list f = List.concat_map f list
(* So `let* x = l in g x` is the same of `l >>= fun x -> g x` *)
nice no?
And now, we can rewrite our example:
let cart_fun modifier list1 list2 =
let* x = list1 in
let* y = list2 in
[modifier x y]
And voila ! Even:
let cart_fun modifier list1 list2 =
let process_list_2 fst_acc =
List.fold_left
(fun snd_acc y -> (modifier x y) :: snd_acc)
fst_acc
list2
in
let result = List.fold_left process_list_2 [] list1 in
List.rev result
Is "more direct" I think it is nice to see how OCaml is expressive!
Related
So I am currently trying to figure out how to write a function where it takes 2 lists of equal lengths and multiplies the same position of both lists through folding, and returns the result as a new List.
eg) let prodList [1; 2; 3] [4; 5; 6] ;;
==> (through folding) ==> [1*4; 2*5; 3*6]
==> result = [4; 10; 18]
I feel like I need to use List.combine, since it will put the values that need to be multiplied into tuples. After that, I can't figure out how to break apart the tuple in a way that allows me to multiply the values. Here is what I have so far:
let prodLists l1 l2 =
let f a x = (List.hd(x)) :: a in
let base = [] in
let args = List.rev (List.combine l1 l2) in
List.fold_left f base args
Am I on the right track?
You can use fold_left2 which folds two lists of the same length. The documentation can give you more details (https://caml.inria.fr/pub/docs/manual-ocaml/libref/List.html):
val fold_left2 : ('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
List.fold_left2 f a [b1; ...; bn] [c1; ...; cn] is f (... (f (f a b1 c1) b2 c2) ...) bn cn. Raise Invalid_argument if the two lists are determined to have different lengths.
Another way is to fold the output of combine as you have suggested, I would recommend you to try it by yourself before looking at the solution bellow.
Solution:
let prod_lists l s =
List.rev (List.fold_left2 (fun acc a b -> (a * b) :: acc) [] l s);;
let prod_lists' l s =
List.fold_left (fun acc (a, b) -> (a * b) :: acc) [] (List.rev (List.combine l s));;
First let me note using fold to implement this operation seems a bit forced, since you have to traverse both lists at the same time. Fold however combines the elements of a single list. Nonetheless here is an implementation.
let e [] = []
let f x hxs (y::ys) = (x*y) :: hxs ys
let prodList xs ys = List.fold_right f xs e ys
Looks a bit complicated, so let me explain.
Universal Property of fold right
First you should be aware of the following property of fold_right.
h xs = fold_right f xs e
if and only if
h [] = e
h (x::xs) = f x (h xs)
This means that if we write the multiplication of lists in the recursive form below, then we can use the e and f to write it using fold as above. Note though we are operating two lists so h takes two arguments.
Base case - empty lists
Multiplying two empty lists returns an empty list.
h [] [] = []
How to write this in the form above? Just abstract over the second argument.
h [] = fun [] -> []
So,
e = fun [] -> []`
Or equivalently,
e [] = []
Recursive case - non-empty lists
h (x::xs) (y::ys) = x*y :: h xs ys
Or, using just one argument,
h (x::xs) = fun -> (y::ys) -> x*y :: h xs ys
Now we need to rewrite this expression in the form h (x::xs) = f x (h xs). It may seem complicated but we just need to abstract over x and h xs.
h (x::xs) = (fun x hxs -> fun (y::ys) -> x*y :: hxs ys) x (h xs)
so we have that f is defined by,
f = fun x hxs -> fun (y::ys) -> x*y :: hxs ys
or equivalently,
f x hxs (y::ys) = x*y :: hxs ys
Solution as a fold right
Having determined both e and f we just plug then into fold according to the first equation of the property above. And we get,
h xs = List.fold_right f xs e
or equivalently,
h xs ys = List.fold_right f xs e ys
Understanding the implementation
Note that the type of List.fold_right f xs e is int list -> int list, so the fold is building a function on lists, that given some ys will multiply it with the given parameter xs.
For an empty xs you will expect an empty ys and return an empty result so,
e [] = fun [] -> []
As for the recursive case, the function f in a fold_right must implement a solution for x::xs from a solution for xs. So f takes an x of type int and a function hxs of type int list -> int list which implements the multiplication for the tail, and it must implement multiplication for x::xs.
f x hxs = fun (y::ys) -> x*y :: hxs ys
So f constructs a function that multiplies x with y, and then applies to ys the already constructed hxs which multiplies xs to a list.
You mostly have the right idea; you'll want to combine (zip in other languages) the two lists and then map over each tuple:
let prod_lists l1 l2 =
List.combine l1 l2
|> List.map (fun (a, b) -> a * b)
The key is that you can pattern match on that tuple using (a, b).
You can also fold over the combined list, then rev the result, if you don't want to use map.
I am back to coding in OCaml and I missed it so much. I missed it so much I completely lost my reasoning in this language and I hit a wall today.
What I want to do is the combination of elements between a set of n lists.
I decomposed the problem by first attempting the combination of elements between two list of arbitrary sizes.
Assume we have to lists: l1 = [1;2;3] and l2 = [10,20].
What I want to do is obtain the following list:
l_res = [10;20;20;40;30;60]
I know how to do this using loop structures, but I really want to solve this without them.
I tried the following:
let f l1 l2 =
List.map (fun y -> (List.map (fun x -> x * y) l1) l2
But this does not seem to work. The type I get is f : int list -> int list -> int list list but I want f : int list -> int list -> int list
I tried already many different approaches I feel I am over complicating.
What did I miss?
What you are missing is that List.map f [a; b; c] gives [f a; f b; f c] so what you'll get from your function will be
f [a; b; c] [d; e] = [[ad; ae]; [bd; be]; [cd; ce]]
but you want
f [a; b; c] [d; e] = [ad; ae; bd; be; cd; ce]
so you need to use an other iterator, i.e. :
let f l1 l2 =
let res = List.fold_left (fun acc x ->
List.fold_left (fun acc y -> (x * y) :: acc) acc l2
) [] l1 in
List.rev res
or to flatten your result :
val concat : 'a list list -> 'a list
Concatenate a list of lists. The elements of the argument are all
concatenated together (in the same order) to give the result. Not
tail-recursive (length of the argument + length of the longest
sub-list).
val flatten : 'a list list -> 'a list
Same as concat. Not tail-recursive (length of the argument + length of
the longest sub-list).
Some Core-flavoured answers:
open Core.Std
let f1 l1 l2 =
List.map (List.cartesian_product l1 l2) ~f:(fun (x, y) -> x * y)
let f2 l1 l2 =
List.concat_map l1 ~f:(fun x -> List.map l2 ~f:(fun y -> x * y))
let f4 l1 l2 =
let open List.Monad_infix in
l1 >>= fun x ->
l2 >>| fun y ->
x * y
The last answer explicitly (and arguably the two other answers implicitly) makes use of the list monad, which this is a textbook use case of. I couldn't find the list monad in Batteries, which is possibly not so surprising as it's much less widely used than (say) the option or result monads.
let f l1 l2 =
let multiply x = List.map (( * )x) l2 in
l1 |> List.map multiply
|> List.concat
Is there a library function to find List1 minus elements that appear in List2? I've been googling around and haven't found much.
It doesn't seem too trivial to write it myself. I've written a function to remove a specific element from a list but that's much more simple:
let rec difference l arg = match l with
| [] -> []
| x :: xs ->
if (x = arg) then difference xs arg
else x :: difference xs arg;;
Will this do?
let diff l1 l2 = List.filter (fun x -> not (List.mem x l2)) l1
What I ended up actually doing was just writing another function which would call the first one I posted
let rec difference l arg = match l with
| [] -> []
| x :: xs ->
if (x = arg) then difference xs arg
else x :: difference xs arg;;
let rec list_diff l1 l2 = match l2 with
| [] -> l1
| x :: xs -> list_diff (difference l1 x) xs;;
Although the solution I accepted is much more elegant
E.g. if you have a function (fun x -> x+1) and you want to map it to [1; 2; 3]. But you only want to map it when x=1, so that the output is [2; 2; 3]. How do you do this?
Using OCaml, I tried:
let rec foo (input : int list) : int list =
match input with
| [] -> []
| hd::tl -> List.map (fun x -> if x=1 then (x+1)) input;;
And I've tried 'when' statements, but to no avail.
An else branch is missing here.
You're almost there. You just need to make a complete if/else statement:
if x=1 then (x+1) else x
OCaml requires a return value on any branch of above expression.
To be clear, when guard is irrelevant here because it is used for conditional pattern matching. Since pattern matching is redundant in this case, your function could be shortened quite a lot:
let foo input =
List.map (fun x -> if x=1 then x+1 else x) input
You can actually use a when statement, even if I prefer #pad's solution:
let foo (input : int list) : int list =
let rec aux acc input =
match input with
[] -> List.rev acc
| x :: xs when x = 1 -> aux ((x + 1) :: acc) xs
| x :: xs -> aux (x :: acc) xs
in
aux [] input
For [1;2;3;4;5], I want to return [[1;2;3;4;5];[2;3;4;5];[3;4;5;];[4;5];[5];[]]
I'm trying to use the List library but I'm unsure how to. So far, I know I have to use List.tl to get the list without the first element
let rec tailsoflist (l : 'a list) : 'a list list =
match l with
[] -> [[]]
| x::xs -> l::(tails xs)
I did this recursively but now I want to just use the list library without using recursion.
let tails (l : 'a list) : 'a list list
EDIT: Sorry guys, what I specified for the function to return is incorrect. Just updated it with the correct output.
As I said in the comment, these are not the tails of l but copies of the tails of l:
# let tails l = List.fold_right (fun e acc -> (e::(List.hd acc))::acc) l [[]] ;;
val tails : 'a list -> 'a list list = <fun>
# tails [1; 2; 3; 4] ;;- : int list list = [[1; 2; 3; 4]; [2; 3; 4]; [3; 4]; [4]; []]
There is no good way to write that function in terms of the built-in functions.
The answer you give in your question is fine but it would be more idiomatic to not annotate the types and use function:
let rec tails = function
| [] -> [[]]
| _::xs' as xs -> xs::tails xs'
Other languages, like F#, provide a List.unfold function that tails can be written in terms of.
Ah, the old trick to accumulate on the original list to cast tails as a catamorphism. This is done without explicit recursion using just functions on the List module:
let tails l = List.rev ( [] :: snd (List.fold_right
(fun _ (t,ts) -> List.tl t, t::ts) l (l, [])) )
It produces the tails as you expect:
# tails [1;2;3;4;5];;
- : int list list = [[1; 2; 3; 4; 5]; [2; 3; 4; 5]; [3; 4; 5]; [4; 5]; [5]; []]
and the tails are the actual structural tails of the input list, so that List.tl l == List.hd (List.tl (tails l)).
"Without using recursion"... why ? Recursion is a useful tool, even outside the List library.
let rec suffixes = function
| [] -> [[]]
| hd::tl as suff -> suff :: suffixes tl
Your function (which doesn't compile because you use tails instead of tailsoflist) returns the list of suffixes of a list. Due to the list structure, it's easier to compute than the prefixes.
You can express the prefixes from the suffixes :
let prefixes li = List.map List.rev (suffixes (List.rev li));;
You could do a direct version using an accumulator:
let prefixes li =
let rec pref acc = function
| [] -> List.rev acc :: []
| hd::tl -> List.rev acc :: pref (hd :: acc) tl
in pref [] li
and express it using List.fold_left if you want to avoid recursion, but this is convoluted so you should prefer the direct version in my opinion:
let prefixes li =
let acc, res =
List.fold_left
(fun (acc, res) e -> (e :: acc), (List.rev acc :: res))
([], []) li in
List.rev acc :: res
Finally, it is possible to destroy your brain with a version using continuations, but I don't remember the exact code. Roughly, the continuation is equivalent to the "accumulator" of the direct version.