Modules in OCaml are useful for organizing code into logical units, while interfaces (sig) define what is exposed outside the module.
Simple Module with Signature
module Example : sig
val the_meaning_of_life_the_universe_and_everything : int
val subtract_one : int -> int
end = struct
let the_meaning_of_life_the_universe_and_everything = 42
let subtract_one x = x - 1
end
let one_less_than_the_meaning_of_life_etc =
Example.subtract_one Example.the_meaning_of_life_the_universe_and_everything
assert (one_less_than_the_meaning_of_life_etc = 41)
Abstract Type
You can expose a type t without revealing what it actually is:
module Abstract_type_example : sig
type t
val to_int : t -> int
val zero : t
val one : t
val add : t -> t -> t
end = struct
type t = int
let to_int x = x
let zero = 0
let one = 1
let add = ( + )
end
let two = Abstract_type_example.add Abstract_type_example.one Abstract_type_example.one
let four = Abstract_type_example.to_int (Abstract_type_example.add two two)
assert (four = 4)
Your Turn: Complete the Fraction Module Signature
Add the necessary signatures to expose the create and value functions.
module Fraction : sig
type t
(* TODO: Add signatures for create and value *)
end = struct
type t = int * int
let create ~numerator ~denominator = numerator, denominator
let value (numerator, denominator) =
Float.of_int numerator /. Float.of_int denominator
end