1

I distinguish three organisation levels while programming: the library level, the component level and the application level. A library defines functions to solve a range of related problems or preform related operations in tools and no policies manner. An application lets several libraries interact and defines policies for diagnostic, error handling, internationalisation,… A component sits between the library and the application, it handles low-level errors and produce diagnostics, it might old global state and is aware of other components.

Now I have a library implemented as a functor parametrised by a module holding a constant n and values associated to different values of n have incompatible types—which is the purpose of implementing the library as a functor. I call such a configuration a hard configuration, because it must somehow be hard-coded in the program.

Now I am facing the following problem: In this setting, I want to allow the user of the program to choose the value of n for the duration of the program. Since the library is a functor, one feels forced to write the component interfacing the library to the program as a functor. But I want the choosed value of n to be a property of the component, not of the application, and I want component to be regular modules (no functor allowed).

How can I wrap a parametric library (implemented as a functor) in a non-parametric component, so that parameters can be chosen when the application starts? I insist on being able to express the application logic at the highest level in terms of non parametric modules, and want to avoid russian-dolls-alike parametrised modules at this level.

user40989
  • 2,860
  • 18
  • 35

1 Answers1

2

This sounds exactly like the intended use-case of first-class modules:

A typical use of first-class modules is to select at run-time among several implementations of a signature.

http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec230

Another thought would be to implement component config parameters as mutable cells, something like this:

module Component :
sig
  val init : ?foo:int -> ?bar:float -> ?baz:string -> unit -> unit
  val foo : unit -> int
  val bar : unit -> float
  val baz : unit -> string
end = struct
  module Default =
  struct
    let foo = 0
    let bar = 0.
    let baz = ""
  end
  let store_foo = ref Default.foo
  let store_bar = ref Default.bar
  let store_baz = ref Default.baz
  let init ?(foo=Default.foo) ?(bar=Default.bar) ?(baz=Default.baz) () =
    ( store_foo := foo
    ; store_bar := bar
    ; store_baz := baz
    )
  let foo () = !store_foo
  let bar () = !store_bar
  let baz () = !store_baz
end
lebowski
  • 136
  • 2