# Modules and generic type signature

**URL:** <https://discuss.ocaml.org/t/modules-and-generic-type-signature/3871>\
**Category:** Learning\
**Created:** [May 30, 2019, 10:23pm UTC](https://discuss.ocaml.org/t/modules-and-generic-type-signature/3871 "2019-05-30T22:23:38Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![mark.sandhu](https://avatars.discourse-cdn.com/v4/letter/m/bbce88/32.png) [@mark.sandhu](https://discuss.ocaml.org/u/mark.sandhu)\
**Post date:** [May 30, 2019, 10:23pm UTC](https://discuss.ocaml.org/t/modules-and-generic-type-signature/3871/1 "2019-05-30T22:23:38Z")

</div>

Hi everyone,

I am new to Ocaml and functional programming. I have been working on a toy project where I am trying to get comfortable with the Ocaml module system. Btw, I am using the jane street base library.

Basically, I have a module of type:

```ocaml
module type CONFIG = sig
  type 'a t

  val tCol : 'a t -> 'a

  val fCol : 'a t -> 'a list

  val makeCol : 'a -> 'a list -> 'a t
end

```

And a Functor that maps over the `Comparator.S` module.

```ocaml
module MakeConfig (C : Comparator.S) = struct
  type 'a t =
    {
      tcol : 'a;
      fcol : ('a, C.comparator_witness) Set.t
    }

  let tCol { tcol = tocolumn; fcol = _ } = tocolumn

  let fCol { tcol = _; fcol = fromcolumn } = Set.to_list fromcolumn

  let makeCol t_col f_col =
    {
      tcol = t_col;
      fcol = Set.of_list (module C) f_col
    }
end

```

This allows me to make modules with multiple implementations of the `Comparator` e.g.

```ocaml
module StringConfig = MakeConfig (String)

```

How do I go about about adding the module type signature? I am trying to do something like this,

```ocaml
module StringConfig : CONFIG with type 'a t = string t = MakeConfig (String)

```

Is this possible in Ocaml with the record type? Or if there is a better way to design the type.

Thanks,

---

<div class="post-metadata">

**Author:** ![octachron](https://avatars.discourse-cdn.com/v4/letter/o/49beb7/32.png) [@octachron](https://discuss.ocaml.org/u/octachron)\
**Post date:** [May 31, 2019, 11:48am UTC](https://discuss.ocaml.org/t/modules-and-generic-type-signature/3871/2 "2019-05-31T11:48:44Z")

</div>

There is two issue, first your module type is not adapted to your functor result.  
Indeed `makeCol` has type `C.t -> C.t list > C.t t`. Thus, you might have intended to write:

```auto
module type CONFIG = sig
  type elt
  type 'a t
  val tCol: 'a t -> 'a
  val fCol: 'a t -> 'a list
  val makeCol: elt -> elt list -> elt t
end

```

Then if you want to hide the implementation of `'a t` in `StringConfig` you can do it with

```auto
module StringConfig
  : CONFIG with type elt := string
  = MakeConfig(String)

```

But then, the only to produce a value of type `'a t` is through `makeCol` which only produces values of type `string t`. Therefore, it might make sense to remove the type parameter of `t` by making it specialized for `elt t` . Or, you can keep the implementation visible with:

```auto
module StringConfig
  : CONFIG with type elt := string
      and type 'a t = MakeConfig(String).t
  = MakeConfig(String)

```

But then, this kind of decision is generally make at the functor level.  
So you would either define `MakeConfig` as

```auto
module MakeConfig(C : Comparator.S) : CONFIG with type elt := C.t = ...

```

Or if you want to keep the type definition visible, you need to move it to the signature.  
You can then either use add the type definition first and then include the `CONFIG` module type after removing the types already defined

```auto
module MakeConfig(C : Comparator.S) : sig
    type 'a t =
    {
      tcol : 'a;
      fcol : ('a, C.comparator_witness) Set.t
    }
   include CONFIG with type elt := C.t and type 'a t:= 'a t
  end = ...

```

or you can update the module type itself:

```auto
module type CONFIG = sig
  type elt
  type witness
  type 'a t =
    {
      tcol : 'a;
      fcol : ('a, witness) Set.t
    }
  val tCol: 'a t -> 'a
  val fCol: 'a t -> 'a list
  val makeCol: elt -> elt list -> elt t
end

module MakeConfig(C : Comparator.S) 
  : CONFIG with type elt := C.t and type witness:= C.comparator_witness
  = ...

```

---

<div class="post-metadata">

**Author:** ![mark.sandhu](https://avatars.discourse-cdn.com/v4/letter/m/bbce88/32.png) [@mark.sandhu](https://discuss.ocaml.org/u/mark.sandhu)\
**Post date:** [May 31, 2019, 5:00pm UTC](https://discuss.ocaml.org/t/modules-and-generic-type-signature/3871/3 "2019-05-31T17:00:53Z")

</div>

Hi @octachron,

Thank you very much for the detailed explanation.

I ended up with the following module type signature:

```ocaml
module type CONFIG = sig
  type elt
  type 'a t

  val tCol : 'a t -> 'a

  val fCol : 'a t -> 'a list

  val makeCol : elt -> elt list -> elt t
end

```

And the functor as the following:

```ocaml
module MakeConfig (C : Comparator.S)
  : CONFIG with type elt := C.t = ...

```

My goal was to provide the client with a function which, when supplied with a comparator module will produce the CONFIG module. The final function looks like the following:

```ocaml
val prepareConfig :
  (module Core.Comparator.S with type t = 'a) ->
  (module CONFIG with type elt = 'a) = <fun>

let prepareConfig
    (type a)
    (module C : Comparator.S with type t = a) =
  (module struct
    type elt = a
    include MakeConfig (C)
  end : CONFIG with type elt = a)

```

Thanks for the help.
