f# - simple iterate on list of pairs - list

I need to go through a list of pairs and check for one of the values in the pair. Say I got this list:
let listOfPairs = [("Joe",100);("Bo",5);("Morten",60)]
And I have to check whether the int value of the pair is equal to 100 or not. I'm not looking for the List.exist method but rather some way to check this with pattern matching, going through every pair in the list and check if the value is 100 or not.
I've obviously tried a lot thing myself but it's too bad to have any good influence in this post. Any ideas or suggestions are very appreciated, thanks in advance.

If you don't want to use List.exist then you could write a recursive function that pattern matches to extract the value:
let rec listContainsHundred = function
| (_, 100)::_ -> true
| _::tail -> listContainsHundred tail
| [] -> false
Otherwise a simple solution with List.exists would be:
List.exists (snd >> ((=) 100)) listOfPairs

Related

Different result in OCaml and ReasonML

There is a case mapping two vectors into a single vector. I expected that the result of both ML should be same. Unfortunately, the result of ReasonML is different. Please help and comment how to fix it.
OCaml
List.map2 (fun x y -> x+y) [1;2;3] [10;20;30];;
[11;;22;;33]
ReasonML
Js.log(List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30]))
[11,[22,[33,0]]]
This is the same result. If you run:
Js.log([11,22,33]);
You'll get:
[11,[22,[33,0]]]
The result is the same, but you're using different methods of printing them. If instead of Js.log you use rtop or sketch.sh, you'll get the output you expect:
- : list(int) = [11, 22, 33]
Js.log prints it differently because it is a BuckleScript binding to console.log, which will print the JavaScript-representation of the value you give to it. And lists don't exist in JavaScript, only arrays do.
The way BuckleScript represents lists is pretty much the same way it is done natively. A list in OCaml and Reason is a "cons-cell", which is essentially a tuple or a 2-element array, where the first item is the value of that cell and the last item is a pointer to the next cell. The list type is essentially defined like this:
type list('a) =
| Node('a, list('a))
| Empty;
And with this definition could have been constructed with:
Node(11, Node(22, Node(33, Empty)))
which is represented in JavaScript like this:
[11,[22,[33,0]]]
^ ^ ^ ^
| | | The Empty list
| | Third value
| Second value
First value
Lists are defined this way because immutability makes this representation very efficient. Because we can add or remove values without copying all the items of the old list into a new one. To add an item we only need to create one new "cons-cell". Using the JavaScript representation with imagined immutability:
const old = [11,[22,[33,0]]];
const new = [99, old];
And to remove an item from the front we don't have to create anything. We can just get a reference to and re-use a sub-list, because we know it won't change.
const old = [11,[22,[33,0]]];
const new = old[1];
The downside of lists is that adding and removing items to the end is relatively expensive. But in practice, if you structure your code in a functional way, using recursion, the list will be very natural to work with. And very efficient.
#Igor Kapkov, thank you for your help. Base on your comment, I found a pipeline statement in the link, there is a summary.
let a = List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30] )
let logl = l => l |> Array.of_list |> Js.log;
a |> logl
[11,22,33]

How to implement recursive function to simplify polynomial terms with sorted tuple list?

I'm trying to implement a function to add like terms of a sorted list of tuples (first number represents polynomial's constant, the second represents the power). I'm an ocaml noob and don't really know what I'm doing wrong or how to do this correctly.
I tried to write it, but it doesn't work
https://gyazo.com/d37bb66d0e6813537c34225b6d4048d0
let rec simp list =
match list with
| (a,b)::(c,d)::remainder where b == d -> (a+c,b)::simp(remainder)
| (a,b)::(c,d)::remainder where b != d -> (a,b)::(c,d)::simp(remainder)
| _ -> list;;
This should combine all the terms with the same second value and just return one tuple with their first values added to the new list. ie: [(3,2);(4,2)] -> [(7,2)].
I am not familiar with the where keyword - there is ocaml-where which provides it, but it seems to be doing something different than what you are expecting. As such, the syntax is just wrong, and where is unexpected.
You probably meant when instead of where.

OCaml Error involving lists

I'm still fairly new to OCaml, and would like some assistance on optimizing code.
I'm trying to multiply each element of a given list by the list's last element.
Here's a snippet of my code:
(* Find the last element of a function *)
let rec lastE = function
| [] -> []
| [x] -> x
| _ :: t -> lastE t;;
(*multiply a list by the last element*)
let rec lmul list =
match list with
[] -> []
| hd::tl -> (hd *. (lastE tl)) :: lmul tl;;
When I run the code I get this error message:
Error: This expression has type float list but
an expression was expected of type 'a list list
I'm been studying it for a while, but any assistance on this problem will be much appreciated.
To rephrase differently what Dave Newman is telling you, your basic problem is that lastE needs to handle an empty list differently. If lastE is supposed to return a number, it has to return a number in all cases. As it stands, lastE returns a list when it receives an empty list.
If you don't want to use List.map (again as Dave Newman suggests), you might at least consider calling lastE just once rather than once for each element of the list. This will make a big difference for long lists.

Enumerating all pairs constructible from two lazy lists in OCaml

I am attempting to enumerate the set of all pairs made of elements from two lazy lists (first element from the first list, second element from the second list) in OCaml using the usual diagonalization idea. The idea is, in strict evaluation terms, something like
enum [0;1;2;...] [0;1;2;...] = [(0,0);(0,1);(1;0);(0;2);(1;1);(2;2);...]
My question is: how do you define this lazily?
I'll explain what I've thought so far, maybe it will be helpful for anyone trying to answer this. But if you know the answer already, you don't need to read any further. I may be going the wrong route.
I have defined lazy lists as
type 'a node_t =
| Nil
| Cons of 'a *'a t
and 'a t = ('a node_t) Lazy.t
Then I defined the function 'seq'
let seq m =
let rec seq_ n m max acc =
if n=max+1
then acc
else (seq_ (n+1) (m-1) max (lazy (Cons((n,m),acc))))
in seq_ 0 m m (lazy Nil)
which gives me a lazy list of pairs (x,y) such that x+y=m. This is what the diagonal idea is about. We start by enumerating all the pairs which sum 0, then all those which sum 1, then those which sum 2, etc.
Then I defined the function 'enum_pair'
let enum_pair () =
let rec enum_pair_ n = lazy (Cons(seq n,enum_pair_ (n+1)))
in enum_pair_ 0
which generates the infinite lazy list made up of: the lazy list of pairs which sum 0, concatenated with the lazy lists of pairs which sum 1, etc.
By now, it seems to me that I'm almost there. The problem now is: how do I get the actual pairs one by one?
It seems to me that I'd have to use some form of list concatenation (the lazy equivalent of #). But that is not efficient because, in my representation of lazy lists, concatenating two lists has complexity O(n^2) where n is the size of the first list. Should I go for a different representations of lazy lists? Or is there another way (not using 'seq' and 'enum_pair' above) which doesn't require list concatenation?
Any help would be really appreciated.
Thanks a lot,
Surikator.
In Haskell you can write:
concatMap (\l -> zip l (reverse l)) $ inits [0..]
First we generate all initial segments of [0..]:
> take 5 $ inits [0..]
[[],[0],[0,1],[0,1,2],[0,1,2,3]]
Taking one of the segments an zipping it with its reverse gives us one diagonal:
> (\l -> zip l (reverse l)) [0..4]
[(0,4),(1,3),(2,2),(3,1),(4,0)]
So mapping the zip will give all diagonals:
> take 10 $ concatMap (\l -> zip l (reverse l)) $ zipWith take [1..] (repeat [0..])
[(0,0),(0,1),(1,0),(0,2),(1,1),(2,0),(0,3),(1,2),(2,1),(3,0)]
In the mean time I've managed to get somewhere but, although it solves the problem, the solution is not very elegant. After defining the functions defined in my initial question, I can define the additional function 'enum_pair_cat' as
let rec enum_pair_cat ls =
lazy(
match Lazy.force ls with
| Nil -> Nil
| Cons(h,t) -> match Lazy.force h with
| Nil -> Lazy.force (enum_pair_cat t)
| Cons (h2,t2) -> Cons (h2,enum_pair_cat (lazy (Cons (t2,t))))
)
This new function achieves the desired behavior. By doing
enum_pair_cat (enum_pair ())
we get a lazy list which has the pairs enumerated as described. So, this solves the problem.
However, I am not entirely satisfied with this because this solution doesn't scale up to higher enumerations (say, of three lazy lists). If you have any ideas on how to solve the general problem of enumerating all n-tuples taken from n lazy lists, let me know!
Thanks,
Surikator.

Value of the last element of a list

how to get the value of the last element of a List? I've noted that List.hd (or .Head) return an item, while List.tl (or .Tail) returns a List.
Is rev the List and get the hd the only way around? Thanks.
Try this function. It uses recursion, though it gets optimised to iteration anyway since it's tail recursion. In any case, it is most likely quicker than reversing the entire list (using List.rev).
let rec last = function
| hd :: [] -> hd
| hd :: tl -> last tl
| _ -> failwith "Empty list."
The answer of Pavel Minaev is definitely worth taking into account, however. Nonetheless, the algorithm you have requested may be useful in some rare cases, and is the most efficient way to go about the task.
In general, if you need to do this, you're doing something wrong. Since F# lists are single-linked, accessing the last element is costly - O(N), where N is size of list. Try to rewrite your algorithm so that you always access the first element, not the last (which is O(1)). If you cannot do so, chances are good that your choice of list for a data structure wasn't correct in the first place.
A quick & dirty way of doing it is by using List.reduce. Assuming the list is called ls,
let lastElement ls = List.reduce (fun _ i -> i) ls
As for efficiency, I agree with Pavel.
A more concise version based on Mitch's answer:
let lastItem = myList |> List.rev |> List.head
The myList list is sent to List.rev function. The result is then processed by List.head
Agreed, not so efficient to get the last element of list, or any other "enumerable" sequence. That said, this function already exists in the Seq module, Seq.last.
As a novice F# developer, I don't see what the harm is in doing the following
let mylist = [1;2;3;4;5]
let lastValue = mylist.[mylist.Length - 1]
Imperative in nature? Yes but no need for recursion.
The regular way to work with lists in F# is to use recursion. The first item in a list is the head (obviously) and the rest of the list is the tail (as oppose to the last item). So when a function recieves a list it processes the head and then recursively processes the rest of the list (the tail).
let reversedList = List.rev originalList
let tailItem = List.hd reversedList
I think you can just write
list.[0..list.Length-1]
You can call List.Head to get the first element of a list, such that the below expression evaluates to true:
let lst = [1;2;3;4;5]
List.head lst = 1
However, calling List.Tail will return every element in the list after the first element, such that the below expression is true:
let lst = [1;2;3;4;5]
List.tail lst = [2;3;4;5]
Like some other people have mentioned, there isn't an efficient way in F# to get the tail end of a list, basic lists just aren't built with that functionality in mind. If you really want to get the last element you're going to have to reverse your list first, and then take the new head (which was the previous tail).
let lst = [1;2;3;4;5]
(List.head (List.rev lst) ) = 5
Below code worked fine with me, I've an array of integers, want to start from the 5th item, then take it minus the item number
Sum of [Array(xi) - Array(xi-5)] where i start at 5
The code used is:
series |> Array.windowed 5
|> Array.fold (fun s x ->
(x |> Array.rev |> Array.head) - (x |> Array.head) + s) 0
|> float
It's a very old question, but just in case someone comes here:
with FSharp 5, you can do x.[^index] where index will start at the end of the array / list.
let a = [1;2;3;4;5;6;7;8;9]
a.[^0] is 9
a.[^1] is 8
etc