OCAML is a statically typed programming language that is part of the ML family. It emphasizes functional programming with a fairly rich type system and an interesting module system.
Everything in OCAML is an expression. Expressions are evaluated by successively performing replacements based on the language rules, until we arrive at an expression that cannot be further evaluated. These are called values. Here is a simple example of such a sequence of evaluations:
(4 + 5) + (2 * 3)
9 + (2 * 3)
9 + 6
15
Every value has a type. The main types in OCAML are:
int
for integers valuesfloat
for double-precision floating point valueschar
for single characters, e.g. 'x'
string
for strings, e.g. "fgrw"
bool
for the two boolean values true
and false
unit
is a special type with only one value, ()
In OCAML there is no automatic coercion between types. We will learn about other more complex types as we move on with the material.
For each language construct we examine three questions:
With that in mind, let’s consider various constructs in turn:
Most of these operators are defined in what is known as the Pervasives module, a library that is automatically included when you start OCAML. We will only discuss addition here, but you can as exercise write down similar instructions for other operators:
int
. The whole expression has type int
.
There is one conditional expression, and unlike most conditional constructs you might have seen in other languages, it is an expression, and thus evaluates to a value.
bool
, and \(e_2\) and \(e_3\) must be of the same type. That type is then the type of the expression.
true
then the expression evaluates to the result of evaluating \(e_2\). If \(e_1\) evaluated to false
, then the expression evaluates to the result of evaluating \(e_3\).
An OCAML program is a sequence of bindings, that look like this:
let x = 2 + 3
Each binding is evaluated by evaluating the expression on the right side of the equal sign, and adding to the dynamic environment the “binding” \(x\mapsto 5\). Later bindings can use the variable “x”. There is also a static environment, used during the type-checking process, which holds a “binding” for the type of \(x\).
So we have two new language constructs to consider: bindings, and variables.
Bindings:
Variables:
Local bindings have a very temporal nature. Instead of extending the environment for all future computations, they only extend it for a specific computation. So we are basically saying “let \(x\) stand for this value while you compute this expression”.
As a little teaser, determine the value of the following expression:
let x = (let x = 3 in x + 1)
in (let x = x + 8 in 2 * x) + x