Chained calls in Ocaml - ocaml

I'm trying to express a set of chained calls in a more imperative fashion. For example, image we have a function that takes a list and an element and it appends the element to the end of the list:
let insert l e =
l # [e]
I want to insert a few elements, one at a time. A functional way to do this could be:
let myList = insert (insert (insert [] 3) 4) 5)
I've recently learned about the |> operator, which helps with expressiveness. Together with currying, it can lead to a clean chaining. The problem is that we need to bind the second argument first. This requires defining a function to reverse the arguments (which is actually what |> does :P):
let myList =
let insertIn l e = insert e l in
[] |>
insertIn 3 |>
insertIn 4 |>
insertIn 5
;;
This is almost what I want, except the need to defined insertIn. Is there a cleaner way to do this?
I was hoping there was a special operator like $ which could represent the return value of the previous function:
let myList =
[] |>
insert $ 3 |>
insert $ 4 |>
insert $ 5
;;

One possible approach, which is common in Haskell, is using flip:
let flip f x y = f y x
let myList =
[] |>
flip insert 3 |>
flip insert 4 |>
flip insert 5
But really, if the insert function is one that you wrote yourself, then you should rather consider changing its definition in either one of these ways:
Flip its arguments so that the list comes last, aka "standard library style":
let insert e l =
l # [e]
let myList =
[] |>
insert 3 |>
insert 4 |>
insert 5
Use a named argument, which allows you to pass it out of order, aka "Core style":
let insert l ~elt:e =
l # [e]
let myList =
[] |>
insert ~elt:3 |>
insert ~elt:4 |>
insert ~elt:5
(Also, a side note: your insert is very inefficient because you're copying the whole l every time; lists are designed to be constructed by prepending elements to the front with ::, not appending to the back.)

let (|>) x f y = f x y;;
let myList =
(((
[] |>
insert ) 3 |>
insert ) 4 |>
insert ) 5
;;
val myList : int list = [3; 4; 5]

Related

What's wrong with my attempt to add 1 to every element in my list in Ocaml?

I don't understand the error message I'm getting or what's wrong with what I'm trying to do
I just want to use List.fold_left to apply my add1 function to this list [1,2,3]
My add1 function should just add 1 to each element, so I would get [2, 3, 4]
My main goal in doing this exercise is just to experiment with List.fold_left. I don't actually care about adding 1, I just choose that function because it seemed easy to write (I'm an ocaml beginner).
My ultimate goal is actually to populate the keys of a empty StringMap using List.fold_left and a function already written elsewhere, so if anyone has insight on that it would also be appreciated
Here's the 1st try (which I tried twice)
let rec add1 = function
| [] -> []
| h::t -> (h+1)::(add1 t) in List.fold_left add1 [1, 2, 3];;
Here's the 2nd try
let a(b) =
let rec add1 = function
| [] -> []
| h::t -> (h+1)::(add1 t)
in
let c = List.fold_left add1 b
in a [1,2,3];;
I think you should start with:
let add x = x + 1
And then build a function that applies a function to a list via List.fold_left:
let apply_f_to_list_elements fn lst = (*use List.fold_left here*)
Are you sure you want List.fold_left and not List.map?
It may help you to see how fold_left can be implemented.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
So consider what's happening when something like a sum function works, when implemented in term of fold_left.
let sum lst =
fold_left (+) 0 lst
If we evaluate sum [1; 2; 3; 4]:
sum [1; 2; 3; 4]
fold_left (+) 0 [1; 2; 3; 4]
fold_left (+) (0 + 1) [2; 3; 4]
fold_left (+) (1 + 2) [3; 4]
fold_left (+) (3 + 3) [4]
fold_left (+) (6 + 4) []
10
We can defined map in terms of fold_left:
let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst
Let's evaluate map (fun x -> x + 1) [5; 2; 6]:
map (fun x -> x + 1) [5; 2; 6]
fold_left f' [] [5; 2; 6]
fold_left f' (5 + 1 :: []) [2; 6]
fold_left f' (2 + 1 :: [6]) [6]
fold_left f' (6 + 1 :: [3; 6]) []
[7; 3; 6]
Now, because of the way we destructure and create lists, the result is backwards. we can overcome this with fold_left by reversing the resulting list.
let map f lst =
let f' init x = f x :: init in
let lst' = fold_left f' [] lst in
List.rev lst'
Or with the |> operator:
let map f lst =
let f' init x = f x :: init in
fold_left f' [] lst |> List.rev
Taking this to the next level
At each iteration, fold_left transforms the first element in a list and an accumulator, into the accumulator for the next iteration. If you want to apply this concept to your StringMap module, consider StringMap.empty which generates an empty StringMap.t, and StringMap.add which take a key, an associated value, and an existing map, and returns a new map with that added mapping.
You can readily use fold_left to take an initially empty map and build it into a complete map step by step. The only question remaining will be what value you choose to associate with each string in your list.
As you seems to confuse map and fold_left I think this quote could help you to understand the difference:
Imagine you have a big dinner with numerous people. You are serving the dish: you go through all the people and replace their empty plates with plates containing food. This is a map operation: the number of plate on the table didn't change, but for each plate, you have done the same action (changing the content of the plate).
Once everything is done, you collect all the dirty plates: This is a fold operation, at the end, there are no more plates on the table, but you have done something for each plates (stacking them) and return the file result (a stack of dirty plates).
In both case, an action is applied systmatically. The difference is that Map preserves the current "structure" (the plates on the table) while Fold removes the structure, and build something else."

I have difficulties with two problems with the langage OCaml

Important: I am only allowed to use List.head, List.tail and List.length
No List.map List.rev ...........etc
Only List.hd, List.tl and List.length
How to duplicate the elements of a list in a list of lists only if the length of the list is odd
Here is the code I tried:
let rec listes_paires x =
if x=[] then []
else [List.hd (List.hd x)]
# (List.tl (List.hd x))
# listes_paires (List.tl x);;
(* editor's note: I don't know where this line is supposed to go*)
if List.length mod 2 = 1 then []
For exemple:
lists_odd [[]; [1];[1;2];[1;2;3];[];[5;4;3;2;1]];;
returns
[[]; [1; 1]; [1; 2]; [1; 2; 3; 1; 2; 3]; []; [5; 4; 3; 2; 1; 5; 4; 3; 2; 1]]
Any help would be very appreciated
thank you all
It looks like that your exercise is about writing recursive functions on lists so that you can learn how to write functions like List.length, List.filter, and so on.
Start with the most simple recursive function, the one that computes the length to the list. Recall, that you can pattern match on the input list structure and make decisions on it, e.g.,
let rec length xs = match xs with
| [] -> 0 (* the empty list has size zero *)
| hd :: tl ->
(* here you can call `length` and it will return you
the length of the list hing how you can use it to
compute the length of the list that is made of `tl`
prepended with `hd` *)
???
The trick is to first write the simple cases and then write the complex cases assuming that your recursive function already works. Don't overthink it and don't try to compute how recursion will work in your head. It will make it hurt :) Just write correctly the base cases (the simple cases) and make sure that you call your function recursively and correctly combine the results while assuming that it works correctly. It is called the induction principle and it works, believe me :)
The above length function was easy as it was producing an integer as output and it was very easy to build it, e.g., you can use + to build a new integer from other integers, something that we have learned very early in our lives so it doesn't surprise us. But what if we want to build something more complex (in fact it is not more complex but just less common to us), e.g., a list data structure? Well, it is the same, we can just use :: instead of + to add things to our result.
So, lets try writing the filter function that will recurse over the input list and build a new list from the elements that satisfy the given predicate,
let rec filter xs keep = match xs with
| [] -> (* the simple case - no elements nothing to filter *)
[]
| x :: xs ->
(* we call filter and it returns the correctly filtered list *)
let filtered = filter xs keep in
(* now we need to decide what to do with `x` *)
if keep x then (* how to build a list from `x` and `filtered`?*)
else filtered (* keep filtering *)
The next trick to learn with recursive functions is how to employ helper functions that add an extra state (also called an accumulator). For example, the rev function, which reverses a list, is much better to define with an extra accumulator. Yes, we can easily define it without it,
let rec rev xs = match xs with
| [] -> []
| x :: xs -> rev xs # [x]
But this is an extremely bad idea as # operator will have to go to the end of the first list and build a completely new list on the road to add only one element. That is our rev implementation will have quadratic performance, i.e., for a list of n elements it will build n list each having n elements in it, only to drop most of them. So a more efficient implementation will employ a helper function that will have an extra parameter, an accumulator,
let rev xs =
(* we will pump elements from xs to ys *)
let rec loop xs ys = match xs with
| [] -> ys (* nothing more to pump *)
| x :: xs ->
let ys = (* push y to ys *) in
(* continue pumping *) in
loop xs []
This trick will also help you in implementing your tasks, as you need to filter by the position of the element. That means that your recursive function needs an extra state that counts the position (increments by one on each recursive step through the list elements). So you will need a helper function with an extra parameter for that counter.

Adding no value to return list

I'm having a problem with understanding how F# works. I come from C# and I think that I'm trying to make F# work like C#. My biggest problem is returning values in the correct format.
Example:
Let's say I have function that takes a list of integers and an integer.
Function should print a list of indexes where values from list match passed integer.
My code:
let indeks myList n = myList |> List.mapi (fun i x -> if x=n then i else 0);;
indeks [0..4] 3;;
However it returns:
val it : int list = [0; 0; 0; 3; 0]
instead of just [3] as I cannot ommit else in that statement.
Also I have targeted signature of -> int list -> int -> int list and I get something else.
Same goes for problem no. 2 where I want to provide an integer and print every number from 0 to this integer n times (where n is the iterated value):
example:
MultiplyValues 3;;
output: [1;2;2;3;3;3]
Best I could do was to create list of lists.
What am I missing when returning elements?
How do I add nothing to the return
example: if x=n then n else AddNothingToTheReturn
Use List.choose:
let indeks lst n =
lst
|> List.mapi (fun i s -> if s = n then Some i else None)
|> List.choose id
Sorry, I didn't notice that you had a second problem too. For that you can use List.collect:
let f (n : int) : list<int> =
[1 .. n]
|> List.collect (fun s -> List.init s (fun t -> s))
printfn "%A" (f 3) // [1; 2; 2; 3; 3; 3]
Please read the documentation for List.collect for more information.
EDIT
Following s952163's lead, here is another version of the first solution without the Option type:
let indeks (lst : list<int>) (n : int) : list<int> =
lst
|> List.fold (fun (s, t) u -> s + 1, (if u = n then (s :: t) else t)) (0, [])
|> (snd >> List.rev)
This one traverses the original list once, and the (potentially much shorter) newly formed list once.
The previous answer is quite idiomatic. Here's one solution that avoids the use of Option types and id:
let indeks2 lst n =
lst
|> List.mapi (fun i x -> (i,x))
|> List.filter (fun x -> (fst x) % n = 0 )
|> List.map snd
You can modify the filter function to match your needs.
If you plan to generate lots of sequences it might be a good idea to explore Sequence (list) comprehensions:
[for i in 1..10 do
yield! List.replicate i i]
If statements are an expression in F# and they return a value. In this case both the IF and ELSE branch must return the same type of value. Using Some/None (Option type) gets around this. There are some cases where you can get away with just using If.

F# Fold while building a list using cons (::) as opposed to concat (#)

I have the following function which does what I want. But is uses the concat (#) operator which is O(n) as opposed to O(1) for the (::) operator
let myFunc s m cs =
let n = s * m
let c = [n - s] // single element list
(n, cs # c) // concat the new value to the accumulated list
let chgLstAndLast =
[0.99; 0.98; 1.02]
|> List.fold (fun (s, cs) m -> myFunc s m cs) (1., [])
The chgLstAndLast returns the last value and list of the results generated:
val chgLstAndLast : float * float list = (0.989604, [-0.01; -0.0198; 0.019404])
I would like to improve the above in three ways.
Use con (::) rather than concat (#)
Move the list accumulation from the myFunc to the List.fold operation
Make sure that the resulting list order remains the same as above (i.e last result is at end of list as opposed to the head)
For example, I would like to write a myFunc like this
let myFunc s m cs =
let n = s * m
let c = n - s // single element, but not as list
(n, c) // No concat here
But when I do, I don't see how to use (::) cons in the Fold function.
If I understand your code correctly, what you want to do is a fold while keeping all intermediary results. This is almost what List.scan does; it also returns the initial state.
let chgLstAndLast data =
let inner s m =
let n = s * m
n, n - s
let processedData = data |> List.scan (fun (s, _) n -> inner s n) (1.0, 1.0)
let lastResult = processedData |> List.reduce (fun _ n -> n)
let seq = processedData |> List.tail |> List.map snd
lastResult, seq
To explain a bit more on this code: first I declare an inner function to make the code cleaner to the exterior world (assuming myFunc isn't needed by other code), then I use scan to get all intermediary results from a fold, which is a built-in way to do your fold + accumulator trick.
The last value is obtained with a reduce trick since there's no built-in "last of list" function, and the intermediary results are the second parts of the processed data, except for the first element which is the initial state.

OCaml code that works on 2 lists. Is there a better way of doing this

I have to iterate over 2 lists. One starts off as a list of empty sublists and the second one has the max length for each of the sublists that are in the first one.
Example; list1 = [[];[];[];]; list2 = [1;2;3]
I need to fill out the empty sublists in list1 ensuring that the length of the sublists never exceed the corresponding integer in list2. To that end, I wrote the following function, that given an element, elem and 2 two lists list and list, will fill out the sublists.
let mapfn elem list1 list2=
let d = ref 1 in
List.map2 (fun a b -> if ((List.length a) < b) && (!d=1)
then (incr d ; List.append a [elem])
else a )
list1 list2
;;
I can now call this function repeatedly on the elements of a list and get the final answer I need
This function works as expected. But I am little bothered by the need to use the int ref d.
Is there a better way for me to do this.
I always find it worthwhile to split the problem into byte-sized pieces that can be composed together to form a solution. You want to pad or truncate lists to a given length; this is easy to do in two steps, first pad, then truncate:
let all x = let rec xs = x :: xs in xs
let rec take n = function
| [] -> []
| _ when n = 0 -> []
| x :: xs -> x :: take (pred n) xs
all creates an infinite list by repeating a value, while take extracts the prefix sublist of at most the given length. With these two, padding and truncating is very straightforwad:
let pad_trim e n l = take n (l # all e)
(it might be a bit surprising that this actually works in a strict language like OCaml). With that defined, your required function is simply:
let mapfn elem list1 list2 = List.map2 (pad_trim elem) list2 list1
that is, taking the second list as a list of specified lengths, pad each of the lists in the first list to that length with the supplied padding element. For instance, mapfn 42 [[];[];[]] [1;2;3] gives [[42]; [42; 42]; [42; 42; 42]]. If this is not what you need, you can tweak the parts and their assembly to suit your requirements.
Are you looking for something like that?
let fill_list elem lengths =
let rec fill acc = function
| 0 -> acc
| n -> fill (elem :: acc) (n - 1) in
let accumulators = List.map (fun _ -> []) lengths in
List.map2 fill accumulators lengths
(* toplevel test *)
# let test = fill_list 42 [1; 3];;
val test : int list list = [[42]; [42; 42; 42]]
(I couldn't make sense of the first list of empty lists in your question, but I suspect it may be the accumulators for the tail-rec fill function.)