DEV Community

david2am
david2am

Posted on • Edited on

OCaml Modules & Libraries (Like JS but Better)

Tired of the OCaml setup rabbit hole?

In 5 minutes, you’ll build your first OCaml program.

Just copy, paste, run.


Index


🟣 Use Modules and Libraries

Let's add some modules, interface files, tests, and more!

Create a Module

In OCaml the concept of module is similar to the one in Python or JavaScript where every file is considered an independent unit of work with its own namespace.

Create a calc.ml file in the lib/ folder and add the following functions:

(* lib/calc.ml *)
let add x y = x + y

let sub x y = x - y
Enter fullscreen mode Exit fullscreen mode

Create a dune File

In Dune it's not enough to create a file to use it as a module, you need to explicitly say it through adding metadata in a dune file.

But before setting the metadata it's important to differentiate between a module and a library in OCaml:

  • Module = single unit of code organization. They form what it's called a compilation unit, a fully independent program from the compiler's perspective
  • Library = packaged collection of modules for distribution

In this occasion you will define everything inside the lib/ folder as a library named math so you could later call the Calc module through it.

Create a dune file in lib/:

; lib/dune
(library
 (name math))
Enter fullscreen mode Exit fullscreen mode

Libraries in OCaml are similar to index files in JavaScript; they expose modules.

Register a Library

In a similar way, if you want to consume a library in another .ml file you need to register it in its adjacent dune file to make it accessible, let's make it accessible to the bin/main.ml file:

In the bin/ folder open the dune file and register the library by its name:

; bin/dune
(executable
 (public_name ocaml_dune)
 (name main)
 (libraries math)) ; Include your module here
Enter fullscreen mode Exit fullscreen mode

Use a Library

Use the open keyword to access the library in main.ml:

(* bin/main.ml *)
open Math

let () = (* in other programming languages this would be to your main function equivalent *)
  let result = Calc.add 2 3 in
  print_endline (Int.to_string result); (* Output: 5 *)
Enter fullscreen mode Exit fullscreen mode

Notice that you also use the Int module from the standard library to convert a number to a string.

Run the Project

Compile and execute your project in watch mode:

dune exec -w my_project
Enter fullscreen mode Exit fullscreen mode

🟣 Create an Interface File

In Dune it's possible to separate your interfaces from your implementation through .mli files. They serve as a way for:

  • Encapsulation: helps define the public interface of a module.
  • Hide implementation details: makes possible to change module internals without affecting other dependent parts.
  • Documentation: it's a good practice to include specifications for clarity.

In the lib/ folder create an .mli file with the same name as its corresponding module, calc.mli in this case:

(* lib/calc.mli *)
val add : int -> int -> int
(** [add x y] returns the sum of x and y. *)
Enter fullscreen mode Exit fullscreen mode

Run the Project

Run:

dune exec -w my_project
Enter fullscreen mode Exit fullscreen mode

Add the sub function to the main.ml file

(* bin/main.ml *)
open Math

let () = (* in other programming languages this would be to your main function equivalent *)
  let result = Calc.add 2 3 in
  print_endline (Int.to_string result); (* Output: 5 *)

  let result = Calc.sub 3 1 in
  print_endline (Int.to_string result) (* Output: 2 *)
Enter fullscreen mode Exit fullscreen mode

As you see if you attempt to use sub it will result in an error, it's because the sub function has not been exposed yet, to solve it add the sub interface in calc.mli:

(* lib/calc.mli *)
val add : int -> int -> int
(** [add x y] returns the sum of x and y. *)

val sub : int -> int -> int
(** [sub x y] returns the difference of x and y. *)
Enter fullscreen mode Exit fullscreen mode

Congratulations! You have created your first code in OCaml!

Happy coding with OCaml! 🚀


Next Steps

Did this help?

Have a question? Comment below — I reply to all!


References

Top comments (1)

Collapse
 
geazi_anc profile image
Geazi Anc

Great article! BTW I didn't know the OCaml Verse, it looks an amazing resource. I'll create a PR to add it in Awesome OCaml and maybe in official OCaml website :)