expose a private type for module extension in OCaml

699 Views Asked by At

I'd like to extend a module but I need access to its private components. Here's an example:

nat.mli:
type t 
val zero : t
val succ : t -> t

nat.ml:
type t = int
let zero = 0
let succ x = x + 1

I'd like to define a new module Ext_nat that defines a double function. I was trying to do something like this.

ext_nat.mli:
include (module type of Nat)
val double : t -> t

ext_nat.ml:
include Nat
let double x = 2 * x

It's not working as I don't have access to the representation of x in the last line.

Now that I'm thinking about this, it may not be such a good idea anyway because this would break the encapsulation of nat. So what is the best way to do this? I could define a new module nat_public where type t = int in the signature, and define nat and ext_nat with a private type t. What do you think?

1

There are 1 best solutions below

0
On

You need to use with type statement. It is possible to write the code below in many different ways, but the idea is always the same.

module type NatSig =
  sig
    type t
    val zero : t
    val succ : t -> t
  end

module type ExtNatSig =
  sig
    include NatSig
    val double : t -> t
  end

module ExtNat : ExtNatSig =
  struct
    type t = int
    let zero = 0
    let succ = fun x -> x + 1
    let double = fun x -> x * 2
  end

module Nat = (ExtNat : NatSig with type t = ExtNat.t)

let z = Nat.zero
let _ = ExtNat.double z

The problem is that as far as I remember it's impossible to achieve this behavior with your file structure: you define your module implicitly with signature in .mli file and structure itself in .ml, so you don't have enough control over you module, that's why I suggest you to reorganize your code a little bit (if it's not a problem).