expose a private type for module extension in OCaml

680 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 answers

0
vonaka 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).