How can I make the find function in ocaml? - ocaml

I have to implement the find function of the module List:
val find : ('a -> bool) -> 'a list -> 'a
This is that I've got, but I don't get the type of the function, so I'm really lost:
let rec find p l= match l with
[]-> raise(Not_found)
| h::t -> if h=p then p else find p t;;
This is the type of my function find:
val find : 'a -> 'a list -> 'a = <fun>

The problem is probably you misunderstood what find was supposed to do.
What you wrote is trying to find p in a list, while find takes p to be a predicate, i.e., a property. You want to find an element x in the list satisfying p, i.e., such that p x is true.

Say you have the following:
type account = { name : string; amount : int; }
let accounts = [{name = "Musterman"; amount = 10}; {name = "Musterfrau"; amount = -90}]
then you can find the account for "Musterman" by using:
List.find (fun a -> a.name = "Musterman") accounts
or accounts with a negative balance using
List.find (fun a -> a.amount < 0) accounts
Having the first argument of List.find be a function returning true when an list item is found makes List.find much more useful than a simple comparison to a know item.

If you have a list like:
let lst = [10; 1; 9; 2; ]
Then your find should take a function like:
find (fun x -> x = 10) lst
The above will find the node in the list which equals 10 if it exists.

Related

ocaml 'a list list function tuples

let sample_table4 = [
[["11"];["21"];["31"];["41"]];
[["12"];["22"];["32"]];
[["13"];["23"]];
[["14"]]];;
This is where I'm stuck with writing a function to get one of these numbers
let tgvc (pos, table) =
match pos with
|[] -> []
|i::[j] -> List.nth (List.nth table (j-1)) (i-1)
|i::_ -> []
;;
val tgvc : int list * 'a list list list -> 'a list = <fun>
I'm supposed to get this signature
tgvc ([3;2],sample_table4);;
val tgvc : int list * ’a list list -> ’a = <fun>
-: string list = ["32"]
What's missing in the function?
I'm sure it has to be recursive now.
Even though it computes the right answer, it's not the right method. The ->[ ] is what's getting me
let rec tgvc (pos, table) = function
|_,[] -> []
|[i;1], h::_ -> List.nth h (i-1)
|[i;j], _::t -> tgvc ([i;j-1], t)
|_ -> []
|[i;j], _::t -> tgvc ([i;j-1], t)
^^^^^^^^^^^^^^^^^
Error: This expression has type int list * 'a list list list -> 'a list
but an expression was expected of type 'a list
What's missing in the function?
A lot of things. Your function simply returns one of many lists of initial input. You don't even use i indice.
I suggest you to think what your function need to do for the given input:
[i; 1], h::_ - you are "in front" of the desirable list
[i; j], _::t - not desirable list yet (some recursion maybe?)
_, [] - empty table
_ - everything else
Edit
You have two problems with your last implementation. First of all in your first and last branches you return [], I guess you would like to exit with an error, so you can throw an exception (via failwith for example). The second problem is actually in the first line: get_table_values_cell (pos, table) = function, it means that you define get_table_values_cell as function with two arguments, you give one explicitly ((pos, table)) and the second is introduced by function keyword. So all you need is to pick only one: get_table_values_cell = function

F# filtering sublist

Here is an input list: [[10;2;10]; [10;50;10]; [10;1;10]].
How would I filter the second element of each sub-list?
Below is my code and when I output the result I get [[10;50;10]] but what I want is [2;50;1]. Is there anyway to fix my code? I am really trying to understand F#. Thanks for the help in advance.
let sub =
let input = [[10;2;10]; [10;50;10]; [10;1;10]]
let findIndex input elem = input |> List.findIndex ((=) elem)
let q = input |> List.filter(fun elem -> findIndex input elem = 1)
printfn "%A" q
The following will get the expected result:
let second (x:List<int>) = x.[1]
let q = List.map second input
List.map is a higher order function that makes a new list by applying a function (the first argument, here the function second that returns the second element of a list) to a list (here input):
[ [10;2;10]; [10;50;10]; [10;1;10] ]
| | |
second second second <--- mapping function
| | |
V V V
[ 2 ; 50 ; 1 ]
Use List.map, not List.filter
List.filter keeps/removes items from an input list based on the function you give it, e.g. List.filter (fun x -> x % 2 = 0) myList would keep only the even numbers in myList. You can get an idea of this functionality based on its type signature, which is val filter: ('a -> bool) -> 'a list -> 'a list, meaning it takes a function (that takes an 'a and returns a boolean: ('a -> bool)), then takes a list, and returns a list of the same type.
List.map, on the other hand, transforms each element of a list into whatever you want, based on a function you give it. In your case you would use it like so:
let input = [[10;2;10]; [10;50;10]; [10;1;10]]
let result = input |> List.map (fun numbers -> numbers.[1])
printfn "%A" result
The signature of List.map is val map: ('a -> 'b) -> 'a list -> 'b list, meaning it takes a function that maps 'as to 'bs (in your case, this would map int lists to ints), takes a list of the first thing, and returns a list of the second thing.
Use List.map and List.tryIndex
Note that if any of the sub-lists are too short, the program will crash. If this is a concern, you can use a safe version of myList.[i]; namely List.tryIndex, which returns None if the item was not found. Try this out:
// Note the last sublist
let input = [[10;2;10]; [10;50;10]; [10;1;10]; [-1]]
let result : int option list = input |> List.map (fun numbers -> List.tryIndex 1 numbers)
printfn "%A" result
// This prints:
// [Some 2; Some 50; Some 1; None]

Information hiding with OCaml records

Given
type 'a set = { insert : 'a -> 'a set; contains : 'a -> bool }
How can I implement
val empty : 'a set
?
I've tried closing over something, say a list, but the return type is wrong.. since it is. (ignoring the fact that the performance characteristics here are terrible :-) )
let empty =
let rec insert_f set a =
match set with
| [] -> a :: []
| k :: rest ->
if k = a then
k :: rest
else
k :: insert_f rest a
in
let rec contains_f set a =
match set with
| [] -> false
| k :: rest ->
if k = key then
true
else contains_f rest a
in
{ insert = insert_f []; contains = contains_f []}
directly writing the empty is not the easiest in such data structure, as you will need to write the insert, which will contains again an insert and so one... So let's write first the insert:
let rec insert : 'a set -> 'a -> 'a set = fun s x -> {
insert = (fun y -> failwith "TODO");
contains = (fun y -> if x = y then true else s.contains y) }
in insert, you want to recursively call insert, but the first parameter will be the record you are writing. So here is the complete solution:
let rec insert : 'a set -> 'a -> 'a set = fun s x ->
let rec ss = {
insert = ( fun y -> insert ss y);
contains = (fun y -> if x = y then true else s.contains y)}
in ss
let rec empty = {
insert = (fun x -> insert empty x);
contains = (fun x -> false)}
First of all, it's bool, not boolean. :)
Second, this definition is quite cumbersome. But you can do something like:
let empty = {
insert=(fun x -> {
insert=(fun x -> assert false);
contains=(fun x-> assert false)});
contains=(fun x -> false)}
with your implementations of insert and contains for non-empty sets in place of "assert false" of course.
A hint for implementing insert and contains: don't use any lists, use compositions of a functions from existing and new sets.
You can find nice examples in e.g. "On Understanding Data Abstraction, Revisited" by W. Cook, that paper is available online.

Addition of element in a list of record (OCaml)

I have a list of record :
list_clients = [{name = "c6"; number = 9}; {name = "c12"; number = 3}; {name = "c17"; number = 6};]
I would like to simply make the sum of all the "number" of each record.
What is the best way? I'm quite beginner with OCaml.
Use a fold:
List.fold_left (fun acc nxt -> nxt.number+acc) 0 list_clients
This takes every element in the list, grabs said element's 'number' field, and adds it to the total thus far, passing along the result.
A bit more explanation about Charles Marsh's answer.
List.fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a takes a function f, an element a and a list [b1; b2; ...; bn] and computes f (... (f (f a b1) b2) ...) bn. It allows you you to easily compute the sum of the elements of a list: List.fold_left (+) 0 l, its maximum element: List.fold_left max (List.hd l) l or anything where you need to go through every element of the list, aggregating it with the previous result.

Returning first value of list of tuples

I'm learning to deal with Lists and Tuples in F# and a problem came up. I have two lists: one of names and one with names,ages.
let namesToFind = [ "john", "andrea" ]
let namesAndAges = [ ("john", 10); ("andrea", 15) ]
I'm trying to create a function that will return the first age found in namesAndAges given namesToFind. Just the first.
So far I have the following code which returns the entire tuple ("john", 10).
let findInList source target =
let itemFound = seq { for n in source do
yield target |> List.filter (fun (x,y) -> x = n) }
|> Seq.head
itemFound
I tried using fst() in the returning statement but it does not compile and gives me "This expression was expected to have type 'a * 'b but here has type ('c * 'd) list"
Thanks for any help!
There are lots of functions in the Collections.List module that can be used. Since there are no break or a real return statement in F#, it is often better to use some search function, or write a recursive loop-function. Here is an example:
let namesToFind = [ "john"; "andrea" ]
let namesAndAges = [ "john", 10; "andrea", 15 ]
let findInList source target =
List.pick (fun x -> List.tryFind (fun (y,_) -> x = y) target) source
findInList namesToFind namesAndAges
The findInList function is composed of two functions from the Collections.List module.
First we have the List.tryFind predicate list function, which returns the first item for which the given predicate function returns true.
The result is in the form of an option type, which can take two values: None and Some(x). It is used for functions that sometimes give no useful result.
The signature is: tryFind : ('T -> bool) -> 'T list -> 'T option, where 'T is the item type, and ('T -> bool) is the predicate function type.
In this case it will search trough the target list, looking for tuples where the first element (y) equals the variable x from the outer function.
Then we have the List.pick mapper list function, which applies the mapper-function to each one, until the first result that is not None, which is returned.
This function will not return an option value, but will instead throw an exception if no item is found. There is also an option-variant of this function named List.tryPick.
The signature is: pick : ('T -> 'U option) -> 'T list -> 'U, where 'T is the item type, 'U is the result type, and ('T -> 'U option) is the mapping function type.
In this case it will go through the source-list, looking for matches in the target array (via List.tryFind) for each one, and will stop at the first match.
If you want to write the loops explicitly, here is how it could look:
let findInList source target =
let rec loop names =
match names with
| (name1::xs) -> // Look at the current item in the
// source list, and see if there are
// any matches in the target list.
let rec loop2 tuples =
match tuples with
| ((name2,age)::ys) -> // Look at the current tuple in
// the target list, and see if
// it matches the current item.
if name1 = name2 then
Some (name2, age) // Found a match!
else
loop2 ys // Nothing yet; Continue looking.
| [] -> None // No more items, return "nothing"
match loop2 target with // Start the loop
| Some (name, age) -> (name, age) // Found a match!
| None -> loop rest // Nothing yet; Continue looking.
| [] -> failwith "No name found" // No more items.
// Start the loop
loop source
(xs and ys are common ways of writing lists or sequences of items)
First let's look at your code and annotate all the types:
let findInList source target =
let itemFound =
seq {
for n in source do
yield target |> List.filter (fun (x,y) -> x = n) }
|> Seq.head
itemFound
The statement yield List.Filter ... means you're creating a sequence of lists: seq<list<'a * 'b>>.
The statement Seq.head takes the first element from your sequence of lists: list<'a * 'b>.
So the whole function returns a list<'a * 'b>, which is obviously not the right type for your function. I think you intended to write something like this:
let findInList source target =
let itemFound =
target // list<'a * 'b>
|> List.filter (fun (x,y) -> x = n) // list<'a * 'b>
|> Seq.head // 'a * 'b
itemFound // function returns 'a * 'b
There are lots of ways you can get the results you want. Your code is already half way there. In place of filtering by hand, I recommend using the built in val Seq.find : (a' -> bool) -> seq<'a> -> 'a method:
let findAge l name = l |> Seq.find (fun (a, b) -> a = name) |> snd
Or you can try using a different data structure like a Map<'key, 'value>:
> let namesAndAges = [ ("john", 10); ("andrea", 15) ] |> Map.ofList;;
val namesAndAges : Map<string,int> = map [("andrea", 15); ("john", 10)]
> namesAndAges.["john"];;
val it : int = 10
If you want to write it by hand, then try this with your seq expression:
let findInList source target =
seq {
for (x, y) in source do
if x = target then
yield y}
|> Seq.head
Like fst use this(below) . This way you can access all the values.
This is from F# interactive
let a = ((1,2), (3,4));
let b = snd (fst a);;
//interactive output below.
val a : (int * int) * (int * int) = ((1, 2), (3, 4))
val b : int = 2