Mutually recursive datatypes - recursion

I'm attempting to create a pair of mutually recursive datatypes to represent a red-black tree in OCaml for a homework assignment. However, I'm very unfamiliar with the OCaml language so I'm having some syntactical issues.
Here's what I have come up with so far:
type 'a red_black_tree =
| RedNode of 'a * ( 'a black_node * 'a black_node )
| BlackNode of 'a black_node
and 'a black_node =
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
| TwoBlackNodes of 'a * ( 'a black_node * 'a black_node )
| BlackLeaf;;
When I input this into ocaml it gives me:
utop # type 'a red_black_tree =
| RedNode of 'a * ( 'a black_node * 'a black_node )
| BlackNode of 'a black_node
and 'a black_node =
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
| TwoBlackNodes of 'a * ( 'a black_node * 'a black_node )
| BlackLeaf;;
Error: Syntax error
Are you not able to reference a sub value of a type from a subtype? Not looking for an actual answer to the problem just syntax clarification.
UPDATE
I had this after the initial attempt but it was stated by the professor that it wasn't a pair of mutually recursive datatypes:
type 'a red_black_tree =
| RedNode of 'a red_node
| BlackNode of 'a black_node
and 'a red_node =
| RedTree of 'a * ( 'a black_node * 'a black_node )
and 'a black_node =
| TwoRedNodes of 'a * ( 'a red_node * 'a red_node )
| TwoBlackNodes of 'a * ( 'a black_node * 'a black_node )
| BlackLeaf;;
UPDATE 2
Problem 3
A red-black tree is a kind of tree sometimes used to organize numerical data. It has two types of nodes, black nodes and red nodes. Red nodes always have one piece of data and two children, each of which is a black node. Black nodes may have either: 1) one piece of data and two children that are red nodes; 2) one piece of data and two children that are black nodes; or 3) no data and no children (i.e., a leaf node). (This isn’t a precise description of red-black trees but suces for this exercise.)
Write a pair of mutually recursive OCaml datatypes that represent red nodes and black nodes in red-black trees. The data should be able to have any type, that is, your type should be polymorphic in the kind of data stored in the tree.

type 'a red_node = 'a * ('a black_node * 'a black_node)
and 'a black_node = ('a * ('a node * 'a node)) option
and 'a node =
Red of 'a red_node
| Black of 'a black_node
An expression that will tell you what sort of node 'n' is, based on the last update to your question.
(* to determine if a black node is a type 1 black node *)
match n with
| Black n' ->
begin match n' with
| Some n'' ->
begin match n'' with
| _, (Red _, Red _) -> "type 1 black node"
| _, (Black _, Black _) -> "type 2 black node"
| _ -> raise (Failure "invalid node")
end
| None -> "leaf node"
end
| Red _ -> "red node";;
On the semantics of types in OCaml: A type name in OCaml must always start with a lowercase letter (e.g. list, array, ref), but type constructors must start with uppercase letters (e.g. Some). The type is an umbrella encompassing all its constructors.
P.S.: I don't think you even need mutually recursive data types for this problem. The following should work:
type 'a node =
Red of 'a * ('a node * 'a node)
| Black of 'a option * ('a node option * 'a node option)

this is an error:
| TwoRedNodes of 'a * ( 'a RedNode * 'a RedNode )
^^^^^^^ ^^^^^^^
Here RedNode should be a type constructor, not a value constructor. I suspect, that you're going to add one more type 'a red_node and define your TwoRedNodes branch as follows:
| TwoRedNodes of 'a * ( 'a red_node * 'a red_node)

Ultimately, the implementation for a pair of mutually recursive datatypes for a red black tree was:
type ’a black_node = Leaf
| RNode of ’a * ’a red_node * ’a red_node
| BNode of ’a * ’a black_node * ’a black_node
and ’a red_node = RedNode of ’a * ’a black_node * ’a black_node;;

Related

SML: Rigorous Way To Parenthesize Function Type

I'm having a bit of difficulty figuring out how to parenthesize a function (when it's legal to add parentheses around certain parts to make the meaning clearer).
For instance, foldl is defined as having type:
foldl : ('a * 'b -> 'b) -> b -> 'a list -> 'b
Now, if I look at foldl's definition, I see:
fun foldl g z [] = z
| foldl g z (x::L) = foldl g (g(x,z)) L;
Based on this, I usually just mentally map g to ('a * 'b -> 'b), z to be of type 'b, and pattern-matching takes care of the list of type 'a list. Finally, the return type is 'b.
However, I thought -> right associates, so wouldn't it be most natural to start by saying "OK, add parentheses like so:
foldl : ('a * 'b -> 'b) -> 'b -> ('a list -> 'b)
What's wrong with this line of thought / what am I misunderstanding about how to add parentheses?
There's nothing wrong with it, it's just redundant.
('a * 'b -> 'b) -> 'b -> ('a list -> 'b), ('a * 'b -> 'b) -> ('b -> ('a list -> 'b)) and ('a * 'b -> 'b) -> 'b -> 'a list -> 'b are all equivalent because -> is right associative. So we usually write the version with the least parentheses (just like one usually writes 3 - 2 - 1 rather than the equivalent (3 - 2) - 1).

OCaml Explicit polymorphic type annotations

I would enjoy to receive some helpful comments concerning an example given on:
http://caml.inria.fr/pub/docs/manual-ocaml-400/manual021.html#toc79
7.12 Explicit polymorphic type annotations
type 'a t = Leaf of 'a | Node of ('a * 'a) t
let rec depth : 'a. 'a t -> 'b = function
|Leaf _ -> 1
| Node x -> 1 + depth x
I understand this example function, but when I try to define a 'map-like' function of type
'a. 'a t -> ('a -> 'b) -> 'b t
e.g.:
let rec tmap: 'a. 'a t ->(f:'a->'b) -> 'b t = function
|Leaf x -> Leaf( f x)
|Node x -> let res = tmap x in Node(res);;
I get the following error:
Characters 67-77:
|Leaf x -> Leaf( f x)
^^^^^^^^^^
Error: This expression has type 'c t but an expression was expected of type
(f:'a -> 'b) -> 'b t
which I do not completely understand.
I would appreciate any helpful comment.
You forgot to get the second argument.
let rec tmap:
'a. 'a t ->(f:'a->'b) -> 'b t = (* asking for two arguments *)
function (* takes only the first argument *)
|Leaf x -> Leaf( f x)
|Node x -> let res = tmap x in Node(res);;
Also, 'b must be polymorphic too, as you want to generate nested tuples as long as you descend through the tree.
This should be, thanks to ivg:
let rec tmap : 'a 'b. 'a t -> f:('a->'b) -> 'b t = fun t ~f ->
match t with
|Leaf x -> Leaf( f x)
|Node x -> let f (a,b) = (f a, f b) in Node ( tmap x ~f ) ;;
You have a few problems, like improperly placed parenthesis around f, forgotten argument to the tmap function in the Node branch, and you've forget the quantifier for 'b. So, finally, with the help of PatJ we can write the following:
type 'a t = Leaf of 'a | Node of ('a * 'a) t
let rec depth : 'a. 'a t -> 'b = function
| Leaf _ -> 1
| Node x -> 1 + depth x
let rec tmap: 'a 'b. 'a t -> f:('a -> 'b) -> 'b t =
fun t ~f -> match t with
| Leaf x -> Leaf (f x)
| Node x ->
Node (tmap ~f:(fun (x,y) -> f x, f y) x)
tmap (Node (Leaf (7,8))) ~f:(fun x -> x + 1, x + 2);;
- : (int * int) t = Node (Leaf ((8, 9), (9, 10)))
many thanks for your great help.
Now my test cases work out as intended:
let int_tree = Node(Node(Leaf((3,-1),(0,4))));;
let char_tree = Node(Node(Leaf(('a','c'),('d','c'))));;
tmap int_tree ~f:(fun x -> x*x);;
- : int t = Node (Node (Leaf ((9, 1), (0, 16))))
tmap char_tree ~f:(fun x -> Char.uppercase x);;
- : char t = Node (Node (Leaf (('A', 'C'), ('D', 'C'))))

How can I create a union type for a tree, where it takes 'a type of key and 'b type of value in OCaml?

I wish to create a bst (binary search tree) union type.
It is either leaf or node. For node, it takes 'a key and 'b value.
I did this:
type 'a*'b bst =
| Node of 'a * 'b * ('a*'b) bst * ('a*'b) bst
| Leaf;;
but it doesn't work
How should I do it?
The syntax for multi-parameter polymorphic types is the following:
type ('a, 'b) bst =
| Node of 'a * 'b * ('a, 'b) bst * ('a, 'b) bst
| Leaf;;
The syntax you are looking for is:
# type ('a, 'b) bst =
| Node of 'a * 'b * ('a,'b) bst * ('a,'b) bst
| Leaf;;
type ('a, 'b) bst = Node of 'a * 'b * ('a, 'b) bst * ('a, 'b) bst | Leaf
In addition, you may get into trouble because 'a needs a comparison operator. This is why in the standard library, the Map and Set modules are implemented as functors, so that it is possible to specify the comparison ordering.
If you decide to go along the 'a polymorphism way, you'll have to use the "magical" default comparison operator compare.
The problem is different in F#, because there are ways to attach a comparison operator to a type.

SML/NJ - the "fun act(f,x) = f(x) ;" signature

Declare on the follow function -
fun act(f,x) = f(x);
Makes the signature -
val act = fn : ('a -> 'b) * 'a -> 'b
What does ('a -> 'b) * 'a -> 'b means ?
It means that act is a function that takes a pair (2-tuple)
('a -> 'b) * 'a
where the first element is a function from 'a to 'b, and the second is a thing of type 'a.
It returns a thing of type 'b.

Type declaration with and

What is benefit of type declaration:
type xxx
and yyy
over
type xxx
type yyy
To give it semantic that one depends on another?
I'm using OcamlWin 4.0 and the code is from C:\OCaml\lib\hashtbl.ml
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
and ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
it compiles. When I change the and to type
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
type ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
compiles as well.
The and keyword is often used when defining mutually recursive declarations
Given your example
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
type ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
would give an Error: Unbound type constructor bucketlist on line 3, characters 20-39. However changing the second type with an and will remove the error.
type ('a, 'b) t =
{ mutable size: int; (* number of entries *)
mutable data: ('a, 'b) bucketlist array; (* the buckets *)
mutable seed: int; (* for randomization *)
initial_size: int; (* initial array size *)
}
and ('a, 'b) bucketlist =
Empty
| Cons of 'a * 'b * ('a, 'b) bucketlist
I can't come up with a reason why it would compile for you in both cases, however if you were using the interpreter and you forget to close it down, then it will have old bindings in its environment.
That is, if you have first evaluated you code with the and keyword then you can keep re-evaluating the code without as bucketlist have already been defined in the invironment.
The and keyword is needed to express mutually recursive definitions. For example,
type t = A | B of u
and u = C | D of t
would no longer compile if you were to replace and with type. In your example, its use is redundant, though.

Resources