Modules and structures in OCaml
Contents:
# Modules and structures
Let’s start by looking at some code we had seen before:
Nil
Cons
and for trees,
Leaf
Node
Now the problem is, both of these functions are named map! And we also don’t want map to be called maplist or maptree cause that makes it harder to remember and call it. So, we’ll have to be clever about this, and encode each of these in a module.
This is how we’d do it for the lists part:
=
The module syntax is as follows:
- Start’s like
module <module-name> = struct - Then you write all your definitions and functions
- Then you write
endand boom. Its a module.
=
Now we can call it nicely using:
map succ
map succ
Of course, OCaml won’t know that a Node is since its inside a module now!. So, how do we tell it?
let t = Node
Node
Like that! Clearly the second version is superior.
# Stacks
Let’s code up a stack in OCaml:
=
The subtle problem with implementing a stack like this is that there is no notion of actually holding the value! So, why not just implement the stack as a list?
=
Note that to create the stack we don’t have a new keyword, we just use the empty stack defined inside the module. Also, ALL OF THESE OPERATIONS ARE immutable. So, if you pop from s, notice how it doesn’t really change s. It gives you a new list in itself.
This is called a functional data structure. It is always immutable!
To evaluate a module, we evaluate each definition from the top to the bottom and that gives us the module value, henceforth called the module.
You cannot pass a module to a function as a parameter
You cannot bind a module with
letCannot return module from a function output
Modules are their very own thing. Unlike classes which you can pass to functions in python (note that those are class objects not classes though!), (python is like jarringly different man!), you cannot do any such shit here.
# Scopes and opening
Okay now lets say we want to create a stack, push to it, and peek at the top value:
let a = peek
I had to write MyList 3 times! That’s bad. We can tell the compiler that I am going to using the MyList module using:
let a =
(*or doing this, using a local open*)
let w =
let open MyList in
empty |> push 0 |> peek
Both are equivalent ways of doing it, their utility depending on what the program calls for. For example, you would typically use the second let expression local opening when you have a long body of code where you want to use this as opposed to a single line.
Another way to write this is to do a global open!
let w = empty |> push 0 |> peek
If you open two global modules which use the same names -> we’re gonna have a problem here!