# Mismatched types between customized compilation units

**URL:** <https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253>\
**Category:** Learning\
**Tags:** type-system, module, types, module-type\
**Created:** [March 5, 2024, 9:44am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253 "2024-03-05T09:44:17Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Marietta\_Galea](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/marietta_galea/32/5172_2.png) [@Marietta\_Galea](https://discuss.ocaml.org/u/Marietta_Galea)\
**Post date:** [March 5, 2024, 9:44am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/1 "2024-03-05T09:44:17Z")

</div>

Hello! I am trying to build a modularized system in OCaml, which consists of two compilation units named `Instr` and `Monitor` along with `run_file.ml` that makes use of these two modules.

`Monitor` has a function called `run_mon` that expects as input another function of type `unit -> t` and the unit value, then it returns a value of type `c`. Meanwhile, `Instr` has a function `run_inst` that expects a unit value and returns a function of type `unit -> r`. This type information is found in the interface files for the two modules mentioned above. The types t, c and r are abstract types inside the interface files for the modules. Inside the implementation files, type t = c = r = unit.

Inside `run_file.ml`, I open these two modules and simply use them as follows:

```auto
let run () = Monitor.run_mon (Instr.run_inst ()) ()

```

However, when trying to compile `run_file.ml`, the compiler raises an error, highlighting Instr.run\_inst ():  
Error: this expression has type unit → Instr.r but an expression was expected of type unit → Monitor.t  
Type Instr.r is not compatible with type Monitor.t

I cannot understand why the compiler is complaining about this issue, however, I am quite new to OCaml so there is something I’m missing here. Any ideas on how to interpret the error and how this issue can be solved would be great.

---

<div class="post-metadata">

**Author:** ![K\_N](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/k_n/32/2793_2.png) [@K\_N](https://discuss.ocaml.org/u/K_N)\
**Post date:** [March 5, 2024, 10:06am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/2 "2024-03-05T10:06:15Z")

</div>

> [@Marietta\_Galea](#):
>
> type t = c = r = unit

My wild guess is that there are mli files for those modules and they don’t export the fact that `r=c`.

Hence the type error, the compiler cannot know outside of these modules that the two function types are equal.

But we would need a bit more details to be sure.

---

<div class="post-metadata">

**Author:** ![Marietta\_Galea](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/marietta_galea/32/5172_2.png) [@Marietta\_Galea](https://discuss.ocaml.org/u/Marietta_Galea)\
**Post date:** [March 5, 2024, 10:23am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/3 "2024-03-05T10:23:00Z")

</div>

Yes, there are mli files for those modules, but the types in those mli files are abstract. So, for instance, the mli file for `Instr` contains the following:

```auto
type r

val run_inst: unit -> (unit -> r)

```

Then, in the ml file of this module is where I specify that r = unit. Similarly for the `Monitor` module.

Is this information hidden from the compiler? Have I done something wrong during compilation or should the implementation (ml) files make it clearer to the compiler in some way that r = c?

---

<div class="post-metadata">

**Author:** ![emillon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emillon/32/1206_2.png) [@emillon](https://discuss.ocaml.org/u/emillon)\
**Post date:** [March 5, 2024, 10:49am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/4 "2024-03-05T10:49:17Z")

</div>

> [@Marietta\_Galea](#):
>
> Is this information hidden from the compiler

- when you compile `x.ml`, the compiler doesn’t know about `x.mli`
- when you compile `y.ml` or `y.mli`, the only facts known about module `X` are the ones in `x.mli` (not `.ml`)
- you can only hide facts using a `.mli`, not add new ones

---

<div class="post-metadata">

**Author:** ![Marietta\_Galea](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/marietta_galea/32/5172_2.png) [@Marietta\_Galea](https://discuss.ocaml.org/u/Marietta_Galea)\
**Post date:** [March 5, 2024, 10:53am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/5 "2024-03-05T10:53:59Z")

</div>

So how should the compilation process look like? I usually compile `x.ml` with `x.mli`, and similarly `y.ml` with `y.mli`, then in a file which uses them both I use the command:

```auto
ocamlc -c x.cmo y.cmo file.ml

```

---

<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:** [March 5, 2024, 11:45am UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/6 "2024-03-05T11:45:48Z")

</div>

The `cmo` files are not used at compilation time, only during linking or archiving. Thus `ocamlc -c x.cmo y.cmo file.ml` is functionally the same as `ocamlc -c file.ml`

The step-by-step process for compiling a compilation unit `u.mli` and `u.ml` :

- compile the cmi files of the dependencies
- compile `u.mli` into `u.cmi`
- compile `u.ml` into `u.cm{o,x}`

Then once all `cm{o,x}` files have been built, they can be either archived into a cm{xa,a} library archive or linked into the final executable.

In other words, the mli file and the cmi describe the specification of your module to the external world, and when you write

```ocaml
type r
val run_inst: unit -> unit -> r

```

your specification tells the external world (aka anyone outside of `instr.ml`) that there is some type `r` which is produced by `run_inst () ()`. Importantly, this implies that the external world cannot make any assumptions about the implementation of the type `r`. (And if there is no other function in the `Instr` module, it is impossible to use values of those types).

---

<div class="post-metadata">

**Author:** ![emillon](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/emillon/32/1206_2.png) [@emillon](https://discuss.ocaml.org/u/emillon)\
**Post date:** [March 5, 2024, 12:01pm UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/7 "2024-03-05T12:01:45Z")

</div>

> [@](#):
>
> So how should the compilation process look like?

What does the whole compilation process look like? Someone can help you write a dune file for this if you’d like.

---

<div class="post-metadata">

**Author:** ![mobileink](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/mobileink/32/3295_2.png) [@mobileink](https://discuss.ocaml.org/u/mobileink)\
**Post date:** [March 5, 2024, 5:08pm UTC](https://discuss.ocaml.org/t/mismatched-types-between-customized-compilation-units/14253/8 "2024-03-05T17:08:13Z")

</div>

> [@Marietta\_Galea](#):
>
> Is this information hidden from the compiler?

No, but it is hidden from clients. So run\_file.ml cannot make use of the fact that in your implementation files you set the abstract types to unit. In particular Monitor.run\_mon expects an arg of type Monitor.t, and that’s all. Clients are not allowed to “know” that monitor.ml defines t as unit.

Try this in the repl:

```auto
# module Monitor: sig
  type t
  val f: unit -> t
end = struct
  type t = unit
  let f = fun() -> ()
end;;
module Monitor : sig type t val f : unit -> t end

#show Monitor.f;;
val f : unit -> Monitor.t

# Monitor.f ();;
- : Monitor.t = <abstr>

```

Note that the compiler gets the type of `Monitor.f` from the signature, not the implementation.

See [5.2.4. Abstract Types · Functional Programming in OCaml](https://courses.cs.cornell.edu/cs3110/2021sp/textbook/modules/abstract_types.html)
