Riccardo Raffini
Riccardo Raffini

Reputation: 396

How to call the constructor of a module

Assuming I have the following module signature and implementation in the same file named monoids.ml:

module type MonoidADT = sig
  type 'a monoid
  (* . . . *)
end

module Monoid : MonoidADT = struct
  type 'a monoid = Monoid of ('a list) * ('a -> 'a -> 'a) * ('a)
  (* . . . *)
end

How am I supposed to use a constructor, of the type defined in the implementation, in an other file (module)? Is it directly accesible or should I create something like a factory function with 'a monoid as return type?

What I tried to do is simply open the module and call its constructor as I would do inside the module, but of course it doesn't work and gives me Unbound constructor Monoid error:

open Monoids.Monoid;;

let boolean_monoid = Monoid ([true; false], ( || ), false);;

Upvotes: 0

Views: 129

Answers (2)

Riccardo Raffini
Riccardo Raffini

Reputation: 396

Apparently defining the type in both signature and implementation resolve the error:

module type MonoidADT = sig
  type 'a monoid = Monoid of ('a list) * ('a -> 'a -> 'a) * ('a)
(* . . . *)
end

module Monoid : MonoidADT = struct
  type 'a monoid = Monoid of ('a list) * ('a -> 'a -> 'a) * ('a)
(* . . . *)
end

But what if I'd like to give a different implementation? The non-abstract signature limits me in the definition of the concrete module.

Upvotes: 0

octachron
octachron

Reputation: 18892

Signature constraints remove information. Moreover, if you remove too much information you can perfectly end up with unusable module.

Typically, when you write

module Monoid : MonoidADT = struct
  ...
end

you are asking the compiler to restrict your monoid to the signature shared by every monoids. And if your monoid module type was the standard one:

module type MonoidADT = sig
  type t
  val e: t
  val ( * ): t -> t -> t
end

this would mean that you are restricting yourself to writing code that is compatible with the one element monoid:

module One = struct
  type t = unit
  let e = ()
  let ( * ) () () = ()
end

This is unlikely to be what you want.

If you only wish to check that your module is a subtype of some module type you can write:

module _ : MonoidADT = Monoid

Upvotes: 1

Related Questions