OCaml matching tuples - ocaml

let add_information info = match info with
(int * int * int) -> int + int + int
;;
let result = add_information (1, 2, 3);;
print_int result;; (* should print 6 here *)
I believe you can match tuples just like you can with lists. Just not sure of the exact format.

Separate with ,s:
let add_info = function
| a, b, c -> a + b + c
Because tuple matching is irrefutable - that is, there is no way for a match to fail - you can also bind tuples with let or in a function argument:
let a, b, c = calc_tuple () in a + b + c

you could also declare a new variable saying something like:
let d,e,f = info in
d+e+f;;

Related

Get element from a type ocaml

New to Ocaml so asking a very basic question.
If I have a type say type foobar = foo * bar and a variable a of type foobar. Is it possible to get just the value of foo from a with a method? Is there any other way than pattern matching? Also, in this case how would you apply pattern matching? Since the type declared is not declared as type foobar = | Foobar of foo * bar?
You can match against a pair like this:
# type intfloat = int * float;;
type intfloat = int * float
# let x : intfloat = (3, 5.5);;
val x : intfloat = (3, 5.5)
# let (int_part, _) = x in int_part;;
- : int = 3
# let (_, float_part) = x in float_part;;
- : float = 5.5
There is a function (not a method) fst that returns the first element of a pair.
# fst x;;
- : int = 3
However, the definition of fst necessarily uses pattern matching:
let fst (a, b) = a
In this definition, the construct (a, b) is a pattern that matches a pair.
Pattern matching is an essential part of OCaml, not just a fancy optional feature.

recursive function that iterates through a list of tuples (int * int) and adds the second value

I want to write a function that iterates through a list of tuples (int * int) and adds the second value of the tuple if the first value of the tuple is the int 0. I came up with the following code however, it raises exception for every case, could anyone point out what is the error in the function? Thanks in advance!
let rec tup x = match x with (a,b)::t -> if a > 0 then b + tup(t) else 0 + tup(t) | []->failwith("a");;
test case: (int * int) list = [(0, 2); (1, 10); (0, 20)] should return 10
You designed this function as recursive, so its last call will always match with []. If you change failwith("a") to 0 function works as expected:
let rec tup x = match x with
(a,b)::t -> if a > 0 then b + tup(t) else tup(t)
| [] -> 0
;;
Results:
# tup [(0,2); (1,10); (0,20)];;
- : int = 10
# tup [(3,4); (1,10); (0,20)];;
- : int = 14
# tup [];; (* You don't want to fail in this case *)
- : int = 0

Use Union-Find to get the equivalence classes

I have a simple code of union-find as below:
let rec find p x =
if p.(x) = x
then x
else
let y = find p (p.(x)) in
p.(x) <- y;
y;;
let union x y p =
p.(find p y) <- p.(find p x);
p
Example:
let a = [|0;1;2;3;4|]
let print_array a =
Array.iter (fun i -> Printf.printf "%i" i; print_string " ") a
let print_union =
let a = union 0 1 a in
print_string "Result union (0, 1): ";
print_array a;
print_string "\n"
the result will be:
Result union (0, 1): 0 0 2 3 4
I am having a hard time to go further to get the disjoint-set.
For instance the example above I want to get: {0,1},{2},{3},{4}
Thank you for your help.
For obvious reasons, you can't print that result without going through the whole structure.
So, you want to collect inhabitants from all of your union-find:
let print_classes a =
(* Let's first create an array for storing the classes *)
let classes = Array.make (Array.length a) [] in
(* Let's now populate it!
I'm going backwards in the array to have nicer printing *)
for i = (Array.length classes) - 1 downto 0
do classes.(a.(i)) <- i :: (classes.(a.(i))) done;
(* And now the printing *)
Array.iter (function
| [] -> ()
| h::t -> Printf.printf "{%d%a}" h
(fun c -> List.iter (fun x -> Printf.fprintf c ",%i" x)) t
)
classes
I used Printf functions for the sake of brevity, you can find their doc here.
Note that this could probably be improved as it creates a potentially big array that may be "almost not" populated. depending on the frequency in which you'll use this function, you may want to store the equivalence class along with the class leader (I had to do that once, I used Set and Map from the stdlib).

Ocaml loop function

I need to make a function that takes as inputs a function f and input b and calls f on b to return (b',c') b' is some result and c' is a boolean. The function needs to then keep calling f on b' as long as c' is true
This is what I wrote:
let rec wwhile (f,b) = match f b with
| (a,c) -> if c then wwhile(f a,c) else a
;;
the idea is I want to get the tuple result of f b and check if c is true but im not sure it using pattern matching is the best way to accomplish this. Also this function gives me a syntax error which im not sure why
heres a sample correct asnwer:
# let f x = let xx = x*x*x in (xx,xx<100);;
val f : int -> int * bool = fn
# wwhile (f,2);;
- : int = 512
figured out correct code:
let rec wwhile (f,b) = match f b with
| (a,c) -> if c then wwhile(f ,a) else a
;;

convert a few 2-tuples to a list of lists

this is a question about ocaml lists and tuples. I have some 2-tuples of numbers (either integers or floats) and I want to convert it to a list of lists (with 2 elements). Assuming that I have defined a num type Int of int | Float of float, the conversion should give the following:
((1,1.0),(0.4,1),(0,0)) => [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
or more precisely
let a = (1,1.0) and b = (0.4,1) and c = (0,0) in
myconversion (a,b,c) ;;
=> [[Int 1;Float 1.0];[Float 0.4; Int 1];[Int 0;Int 0]]
the point being the values a, b, c... are defined in several places in the source files (by people who use different signatures for their tuples).
The difficulty here is that I don't know the types of the elements of the 2-tuples (int or float, that varies depending on the tuple).
Your input data can't be represented in OCaml as you describe it. OCaml is strongly typed. For example, your example input list is an invalid value in OCaml:
# [(1,1.0);(0.4,1);(0,0)];;
Error: This expression has type float but an expression was expected of type
int
So what you describe as the essence of your problem (not knowing the types) is in fact not possible. You'll have to use some other method of representing the input. For example, you could just use floats for everything. Or you could use pairs of strings.
Update
The answer for the rewritten question is the same. In OCaml it's not possible not to know the type of something statically; i.e., at the time you're writing the program (unless it can be any type at all). It's not possible (or necessary) to query the type of something at runtime. So your question doesn't have an answer (at least as far as I can see).
For OCaml, you have to think with the type system rather than against it. After a while you start to really like it (or at least that's how it worked for me). I'd start by writing down the type you want your function myconverstion to have.
Update 2
I'll repeat my advice to treat your inputs as strings. Assuming you've parsed your input up into pairs of strings, here's some code that does what you want:
let myconversion coords =
let c1 s =
if String.contains s '.' then
Float (float_of_string s)
else
Int (int_of_string s)
in
let cp (a, b) = [c1 a; c1 b] in
List.map cp coords
Here's how it works for your input (reinterpreted as strings):
# myconversion [("1", "1.0"); ("0.4", "1"); ("0", "0")];;
- : fi list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
Update 3
Here's some (crude) code that parses a file of numbers into coordinates represented as pairs of strings. It should work as long as the tuples in the input are well formed.
let coords fname =
let ic = open_in fname in
let len = in_channel_length ic in
let buf = Buffer.create 128 in
let () = Buffer.add_channel buf ic len in
let () = close_in ic in
let s = Buffer.contents buf in
let nums = Str.(split (regexp "[^0-9.]+") s) in
let rec mkcoords sofar = function
| [] | [_] -> List.rev sofar
| a :: b :: rest -> mkcoords ((a, b) :: sofar) rest
in
mkcoords [] nums
There are two distinct problems in your setup:
you don't know the type of the tuples parameters
you want to pass them as a single n-ary tuple
For problem 2, you would have to write a function for that type specifically, whereas you could mimic a type level list type by nesting couple of tuples:
myconversion a,(b,c) ;;
The reason is that with that setup, you could write a recursive polymorphic function on the type level list:
val myconversion : type a b. (a,b) -> num list
There would still be a problem on the last element though.
So, assuming that you could pass a sequence to your conversion function, and have it process elements of that sequence one by one, you would still need to find a way of selecting the proper function of pair conversion from the tuple type: that's basically ad-hoc polymorphism, ie. you would need to be able to overload a function on its parameters' types(1). Unfortunately, OCaml doesn't support that out of the box.
One possibility would be perhaps (I have no experience doing that) to implement an extension which would extract the type information of a given expression, and generate the correct code to process it in your own code.
A flexible technique consists in having that extension generate an algebraic description of the tuples types, and use that description as an equality witness in the code which will process the tuples:
type _ w =
| U : (unit * unit) w
| IF : 'a w -> ((int * float) * 'a) w
| FI : 'a w -> ((float * int) * 'a) w
(* other constructors if necessary *)
(* data *)
let a = 1,1.0
let b = 2.0, 2
let c = 3.0, 3
let d = 4, 4.0
let l = a,(b, (c,(d,((),()))))
(* witness *)
let w = IF (FI (FI (IF U)))
(* the type parameter of w should be the same as l type *)
let rec conv : type a b. (a * b) w -> (a * b) -> num list = fun w (x, xs) ->
match w with
U -> []
| IF w' -> let i,f = x in (Int I)::(Float f)::(conv w' xs)
(* etc *)
Here, we encode the type level nil list as (unit * unit) w.
A coalgebraic approach would require to register function overloads to the conversion function polymorphic signature within the extension, and let it pick the right one from the function overload dictionary.
There's a discussion on that topic on the LtU site.
Thanks to everybody who answered. I finally found a solution, using a bit of magic:
# type num = Int of int | Float of float;;
# let to_num x = if Obj.is_int (Obj.repr x) then
Int (Obj.magic (Obj.repr x) : int)
else
Float ((Obj.magic (Obj.repr x) : float));;
# let pair_to_num (a,b) = [to_num a; to_num b];;
# let myconversion (a,b,c) = [pair_to_num a; pair_to_num b; pair_to_num c];;
and the test:
# myconversion ((1,1.0),(0.4,1),(0,0));;
- : num list list = [[Int 1; Float 1.]; [Float 0.4; Int 1]; [Int 0; Int 0]]
# myconversion ((0,0),(1,1.0),(0.4,1));;
- : num list list = [[Int 0; Int 0]; [Int 1; Float 1.]; [Float 0.4; Int 1]]
Magic, the order does not matter and the type is recorded! I can then follow didier's idea to get rid of the pair of superfluous parentheses.