Information hiding with OCaml records - ocaml

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.

Related

How can I make the find function in 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.

Java GuardTypes analogy for OCaml

How do you do, Stackoverflow!
In Java practice there are some issues concerning partially defined functions. Sometimes it's convinient to separate an error handling from the calculation itself. We may utilize an approach called "Guard types" or "Guard decorators".
Consider the simple synthetic example: to guard the null reference. This can be done with the aid of the next class
public class NonNull<T> {
public take() {
return null != this.ref ? this.ref : throw new ExcptionOfMine("message");
}
public NotNull(T ref_) {
this.ref = ref_;
}
private T ref;
}
The question is:
Is there a way to implement the same "Guard type" in OCaml without touching its object model? I believe for the OCaml as the functional programming language to possess enough abstraction methods without objec-oriented technics.
You can use an abstract type to get the same effect. OCaml has no problem with null pointers. So say instead you want to represent a nonempty list in the same way as above. I.e., you want to be able to create values that are empty, but only complain when the person tries to access the value.
module G :
sig type 'a t
val make : 'a list -> 'a t
val take : 'a t -> 'a list
end =
struct
type 'a t = 'a list
let make x = x
let take x = if x = [] then raise (Invalid_argument "take") else x
end
Here's how it looks when you use the module:
$ ocaml
OCaml version 4.02.1
# #use "m.ml";;
module G :
sig type 'a t val make : 'a list -> 'a t val take : 'a t -> 'a list end
# let x = G.make [4];;
val x : int G.t = <abstr>
# G.take x;;
- : int list = [4]
# let y = G.make [];;
val y : '_a G.t = <abstr>
# G.take y;;
Exception: Invalid_argument "take".
There's a concept of Optional types, on which you can effectively pattern match. Example:
let optional = Some 20
let value =
match optional with
| Some v -> v
| None -> 0
You can use simple closures
let guard_list v =
fun () ->
if v = [] then failwith "Empty list"
else v
let () =
let a = guard_list [1;2;3] in
let b = guard_list [] in
print_int (List.length (a ())); (* prints 3 *)
print_int (List.length (b ())) (* throws Failure "Empty list" *)
or lazy values
let guard_string v = lazy begin
if v = "" then failwith "Empty string"
else v
end
let () =
let a = guard_string "Foo" in
let b = guard_string "" in
print_endline (Lazy.force a); (* prints "Foo" *)
print_endline (Lazy.force b) (* throws Failure "Empty string" *)

Removing consecutive duplicates from a list without recursion

I'm supposed to remove consecutive duplicates from an int list without using recursion and using only List.fold, map, filter, fold_left, fold_right.
I almost got it, but the problem with my code is that it checks if each element equals the 2nd element, and not the next element.
For example if let z = int list [3;1;4;5;5;1;1] my code will return [3;4;5] and not [3;1;4;5;1]. I'm not sure how to change it so filter uses a dynamically changing list parameter and not simply the original one (so it doesn't compare each element to the second element (1 in this case) each time):
let dupe (ls: int list) : int list =
List.filter (fun x -> if List.length ls = 0 then true else if x = List.hd (List.tl xs) then false else true) ls
The type of List.filter is this:
# List.filter;;
- : ('a -> bool) -> 'a list -> 'a list = <fun>
Notably, the filter function can see only one element of the list at a time. You need to see two consecutive elements to decide what to do, so I'd say List.filter won't do the job.
You're going to have to use map or one of the folds, I'd say. You can figure out which one(s) will work, with similar reasoning.
(I assume this is the sort of reasoning the assignment is supposed to illustrate. So I'm going to leave it there.)
Without rec
let remove = function
[] -> []
| x::tl ->
let (_,lxRes)=
List.fold_left (
fun (xPrec,lxRes) xCour ->
if xPrec=xCour then
(xCour,lxRes)
else
(xCour,lxRes#[xCour])
) (x+1,[]) (x::tl)
in
lxRes
Test:
# remove [3;1;4;5;5;1;1];;
- : int list = [3; 1; 4; 5; 1]
# remove [1;1];;
- : int list = [1]
# remove [1;1;1;1;2;2;3;4;5;5];;
- : int list = [1; 2; 3; 4; 5]
With rec (just for information)
let rec remove =
function
| [] -> []
| x::[] -> x::[]
| x::y::tl ->
if x=y then remove (y::tl)
else x::remove (y::tl)
Using just List.fold_left can be a little bit more concise than the previous answer. Of course, this will build up the list in reverse order, so we need to reverse the result.
let remove lst =
List.(
lst
|> fold_left
(fun acc x ->
match acc with
| [] -> [x]
| hd::_ when x = hd -> acc
| _ -> x::acc)
[]
|> rev
)
Of course, if you're not allowed to use List.rev we can reimplement it easily using List.fold_left, List.cons and Fun.flip.
let rev lst =
List.fold_left (Fun.flip List.cons) [] lst

Check if a matrix contains a number

I want to check if a matrix of type [[a,b,c][d,e,f]] contains a specific number.
I'm having trouble accessing the list inside the list.
let matrix = [[1;2;3]; [4;5;6]];;
let rec contains mat x = match mat with
| [] -> false
| h::t -> if (h=x) then true else contains t x;;
This work on a one-dimensional list, but I'm just too much of a newbie to get it to work on a two-dimensional.
First off, your function contains is List.mem in the standard library (not that there is anything wrong with reimplementing it to learn OCaml).
Also, if (h=x) then true else contains t x is usually written (h=x) || contains t x.
As for your problem, you need to iterate over each sublist of the matrix (presumably representing a row), and for each row check if it contains the number you're looking for :
# let rec mat_contains mat x = match mat with
| [] -> false
| row::tl -> contains row x || mat_contains tl x;;
val mat_contains : 'a list list -> 'a -> bool = <fun>
# mat_contains matrix 4;;
- : bool = true
As an aside, here it is written using functions in the standard library :
# let mat_contains2 mat x = List.exists (List.mem x) mat;;
val mat_contains2 : 'a list list -> 'a -> bool = <fun>
# mat_contains2 matrix 4;;
- : bool = true

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