Reputation: 99606
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree;;
Is it a type definition, where a
is a type parameter, and tree
is the type name?
In Node of
, is Node
a built-in type of OCaml? What does of
mean?
Thanks.
Upvotes: 2
Views: 683
Reputation: 3028
There are several kinds of type definitions:
From that type definition:
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree;;
Here are roughly the "facts" that the OCaml compiler knows about based on it:
tree
is a unary type constructor. That means that for any type t
, t tree
is a type as well (example: int tree
).Empty
is a 0-ary constructor for 'a tree
. That means that Empty
has type t tree
for any t
.Node
is a 3-ary constructor. Here this means that if a
has type t
, b
has type t tree
, and c has type
t tree, then
Node (a, b, c)has type
t tree(note: that's the same
t`)t tree
. That means that you can use pattern matching (match ... with | Empty -> ... | Node (a, b, c) -> ...
).A definition can also be something that looks like:
type t = existing_type
In that case, t
is just a new neame for the existing_type
.
For example:
type 'a pp = Format.formatter -> 'a -> unit
This means that something that is a int pp
has type Format.formatter -> int -> unit
.
This is the type of a function that takes a formatter and an integer and returns unit
. Such as :
type 'a pp = Format.formatter -> 'a -> unit
module M : sig
val pp_int : int pp
end = struct
let pp_int fmt n = Format.fprintf fmt "%d" n
end
Upvotes: 1
Reputation: 3739
Yes 'a
is a type parameter and tree
is a type name (these are usually called variants in OCaml). This is reversed order from most other languages. Node
is a constructor (called tag in OCaml) and of
is just a keyword in OCaml to specify the types of the constructor arguments. Node
is not a built-in type of OCaml (it is not even a type, but rather, as a I said, a constructor).
Hence Node (5, Empty, Node (6, Empty, Empty))
is something of type int tree
(something like Tree<Int>
in Java).
It may make more sense if you start with a simpler variant.
type shape = Square of int | Rectangle of int * int
Shape
and Rectangle
are tags (again constructors) that I have just made up that allow me to construct values of type shape
(in this case I've chosen to have Shape
take only one argument because only length is needed to specify a square, whereas Rectangle
s need both length and width). Nothing ever has a type of Shape
or Rectangle
, but things can have a type of shape
.
One way to read that line in English is "I have defined a type called shape
. A shape
is either a Square
of a single integer, or a Rectangle
of two integers."
Now maybe for some reason I also want to label my shapes.
type 'label labelledshape = LabelledSquare of 'label * int | LabelledRectangle of 'label * int * int
The quote '
distinguishes that label
is not a type (such as int
), but is rather a variable. This allows me to write something like LabelledSquare ("a label for a square", 5)
which is of type string labelledshape
Note that although this allows for polymorphism, these are not what is known as "polymorphic variants" in OCaml. I will not talk about that here, rather I'll just recommend either looking at OCaml documentation or browsing Stack Overflow for more details on that.
Upvotes: 4