# Basic Module and Functors question

**URL:** https://discuss.ocaml.org/t/basic-module-and-functors-question/1054
**Category:** Learning
**Created:** [November 2, 2017, 6:39pm UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054 "2017-11-02T18:39:20Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![jnavila](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jnavila/32/527_2.png) [@jnavila](https://discuss.ocaml.org/u/jnavila)
#### Post date: [November 2, 2017, 6:39pm UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/1 "2017-11-02T18:39:20Z")

</div>

Hi all,

In the process of learning OCaml while providing something useful, I’m trying to functorize a lib for ploting Kicad electronics schematics while remove a dependency to Lwt. But, it fails miserably. In the setup there’s a painter module that is able to paint primitive shapes to a canvas (here, for SVG output). Then this painter is used by the schematic painter module. I’d like to strip the Lwt\_io dependency from the schematic painter while still providing it in the SVG painter to write the file.

```auto
module type Painter = sig

  (** the canvas of the painter *)
  type t

  (** [get_context ()] @return a new canvas *)
  val get_context: unit -> t

 ( **here the primitive painting functions accepting t** )
end

(** A module able to paint a schematic in a schematic context *)
module type SchPainter = sig
  (** the schematic context *)
  type schContext

  ( **the underlying context** )
  type painterContext

  (** [initial_context ()] @return an new empty context *)
  val initial_context : unit -> schContext

  ( **Here some schematic primitive management** )

  (**[output_context context] retrieve the canvas from the [context]**)
  val output_context: schContext -> painterContext

end

module MakeSchPainter (P: Painter): (SchPainter with type painterContext := P.t) =
struct

( **implement SchPainter** )
....
end

module SvgPainter =
struct

  ( **implement Painter signature** )

  let write (oc:Lwt_io.output_channel) t = ( **code to write the picture to a file** )

end

```

Finally in the main code

```ocaml

module SvgSchPainter = MakeSchPainter(SvgPainter)
open SvgSchPainter

let () =
  ctxt = initial_context () in
  ... ( **ctxt is added content and is now end_context** )
  SvgPainter.write oc (output_context endcontext)

```

This last line does not compile with the error “This expression has type painterContext but an expression was expected of type SvgPainter.t”. `output_context` has indeed the signature `schContext->painterContext` in spite of the `with` clause ni `MakeSchPainter`.

How do I make the public types match so that I can use the functions specific to SvgPainter on them?

---

<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: [November 2, 2017, 9:02pm UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/3 "2017-11-02T21:02:32Z")

</div>

Your code mockup seems to work perfectly fine. In particular the signature of the functor `MakeSchPainter` should expand to

```
functor (P : Painter) ->
  sig
    type schContext
    val initial_context : unit -> schContext
    val output_context : schContext -> P.t
  end

```

since the destructive substitution in the result signature `SchPainter with type painterContext := P.t` would have erased the very existence of the type `painterContext`.

Consequently, it seems plausible that the problem stems from somewhere else in your code.

---

<div class="post-metadata">

### Author: ![theindigamer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/theindigamer/32/610_2.png) [@theindigamer](https://discuss.ocaml.org/u/theindigamer)
#### Post date: [November 2, 2017, 9:07pm UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/4 "2017-11-02T21:07:21Z")

</div>

This is puzzling. I’ve been trying to come up with minimal examples to reproduce this but I can’t.

```auto
module type S = sig
    type t
    val const : t
    val incr : t -> t
end

module Make(X: S): (S with type t := X.t) = struct
    type t = X.t
    let const = X.incr X.const
    let incr = X.incr
end

module X1 : S = struct
    type t = int
    let const = 57
    let incr = (+) 1
end

module X2 = Make(X1);;

X1.incr X2.const;;
- : X1.t = <abstr>
X2.incr X1.const;;
- : X1.t = <abstr>
```

---

<div class="post-metadata">

### Author: ![jnavila](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jnavila/32/527_2.png) [@jnavila](https://discuss.ocaml.org/u/jnavila)
#### Post date: [November 2, 2017, 10:46pm UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/5 "2017-11-02T22:46:59Z")

</div>

Thanks for trying to reproduce.

The strange thing is that looking at the inferred signature of `MakeSchPainter`, `output_context` is as expected:

```ocaml

val output_context: schContext -> P.t

```

But when it is instanciated for real, the resulting module loses the type imposed by destructive substitution.

Merlin gives a strange type to output\_context in SvgSchPainter:

```ocaml
val output_context: schContext ->painterContext®nd

```

I don’t know what this means.

If you’re still interested, I pushed the real project [here](https://github.com/jnavila/plotkicadsch/tree/strip_out_lwt_io)

---

<div class="post-metadata">

### Author: ![theindigamer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/theindigamer/32/610_2.png) [@theindigamer](https://discuss.ocaml.org/u/theindigamer)
#### Post date: [November 3, 2017, 1:11am UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/6 "2017-11-03T01:11:58Z")

</div>

Thanks for sharing the repo, makes it much easier to debug. I think I’ve identified the issue; you’ve not exported the required type signature for the module [here](https://github.com/jnavila/plotkicadsch/blob/080bcd528ef7c29bfdadfc76bf2bcba208580e89/src/kicadsch.mli#L2).

Your export currently looks like:

```auto
module MakeSchPainter(P: KicadSch_sigs.Painter): KicadSch_sigs.SchPainter

```

whereas it should look like

```auto
module MakeSchPainter(P: KicadSch_sigs.Painter): (KicadSch_sigs.SchPainter with type painterContext := P.t)

```

You’re using the signature with substitution while defining the module but you’re not exporting it on the interface (in the .mli file), so other external modules have no way of knowing that you actually made that substitution.

Fixing that removes the type error but gives a build error.

```auto
File "src/kicadsch.ml", line 8, characters 2-27:
Warning 34: unused type painterContext.
File "src/kicadsch.ml", line 1:
Error: Some fatal warnings were triggered (1 occurrences)

```

This can be fixed by erasing [this line](https://github.com/jnavila/plotkicadsch/blob/cc8a300bb8ef56f848d0751e145329a5402335f9/src/kicadsch.ml#L8)

```auto
   type painterContext = P.t

```

as that type isn’t being used. And now the code compiles. 🎉

---

<div class="post-metadata">

### Author: ![jnavila](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jnavila/32/527_2.png) [@jnavila](https://discuss.ocaml.org/u/jnavila)
#### Post date: [November 3, 2017, 8:39am UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/7 "2017-11-03T08:39:26Z")

</div>

Thank you very much for debugging my code 😊 ! I had forgotten this mli file that is useless now.

Just as a learning take away from this, how did you debug the code? Pure scrutiny or could you trail the instance to the mli file with the help of the development tools?

---

<div class="post-metadata">

### Author: ![theindigamer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/theindigamer/32/610_2.png) [@theindigamer](https://discuss.ocaml.org/u/theindigamer)
#### Post date: [November 3, 2017, 2:34pm UTC](https://discuss.ocaml.org/t/basic-module-and-functors-question/1054/8 "2017-11-03T14:34:41Z")

</div>

Thought process:

- Why does Merlin think this is of type `painterContext`?
- Looked at the source code in the `.ml` file - that seems fine.
- Looked at the `.mli` file just to make sure nothing funny is going on in between - aha, there it is!

For the second one, I just guessed that if the type is being set already via `:=`, maybe just commenting out the repeated definition might do the trick, and it worked.
