# Module type and enum type

**URL:** https://discuss.ocaml.org/t/module-type-and-enum-type/5907
**Category:** Learning
**Created:** [June 3, 2020, 4:51pm UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907 "2020-06-03T16:51:27Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![Chimrod](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chimrod/32/6042_2.png) [@Chimrod](https://discuss.ocaml.org/u/Chimrod)
#### Post date: [June 3, 2020, 4:51pm UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907/1 "2020-06-03T16:51:27Z")

</div>

Hello,

I’m tooling with the implementation of modules with a given signature.

Let’s say I have a module type with this signature :

```ocaml
module type T = sig
    type t
end

```

I can provide an implementation and defining the type :

```ocaml
module M_string: T with type t = string = struct type t = string end
module M_variant: T with type t = [`OK] = struct type t = [`OK] end

```

but this does not work with enum types or gadt :

```ocaml
module M2: T with type t = | OK = struct type t = | OK end

```

```auto
9 | module M2: T with type t = | OK = struct type t = | OK end
                               ^
Error: Syntax error

```

Is there an easy solution ? (I’ve simplified the example, but I’m actually including other signatures and I don’t want to rewrite the full signature).

Thanks !

---

<div class="post-metadata">

### Author: ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)
#### Post date: [June 3, 2020, 5:18pm UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907/2 "2020-06-03T17:18:01Z")

</div>

Sum types (including GADTs) need to be declared (given a name), so the best you can do is to define the type outside the module and refer to it from both places, eg:

```auto
type foo = ...
module M : T with type t = foo = struct type t = foo end

```

But actually, depending on what you are doing, you may want to leave `: T with type t = foo` out altogether, and rely on the compiler to check the module signature for you.

Best wishes,  
Nicolás

---

<div class="post-metadata">

### Author: ![yallop](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yallop/32/517_2.png) [@yallop](https://discuss.ocaml.org/u/yallop)
#### Post date: [June 3, 2020, 9:13pm UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907/3 "2020-06-03T21:13:07Z")

</div>

You can use `include` rather than `with` to relate the signature of `M2` to `T`:

```ocaml
module M2: sig
  type t = OK
  include T with type t := t
end =
struct
  type t = OK
end

```

---

<div class="post-metadata">

### Author: ![Chimrod](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chimrod/32/6042_2.png) [@Chimrod](https://discuss.ocaml.org/u/Chimrod)
#### Post date: [June 4, 2020, 8:46am UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907/4 "2020-06-04T08:46:34Z")

</div>

I didn’t thought of the destructive substitution.

The specification explicitaly mention that “There are no type expressions describing (defined) variant types nor record types, since those are always named, i.e. defined before use and referred to by name.” [[https://caml.inria.fr/pub/docs/manual-ocaml/types.html#sss:typexpr-variant-record](https://caml.inria.fr/pub/docs/manual-ocaml/types.html#sss:typexpr-variant-record)] But I do not understand the rationale behind this, as the polymorphic variants does not follow the same scheme.

Is this an old specification ?

---

<div class="post-metadata">

### Author: ![yallop](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yallop/32/517_2.png) [@yallop](https://discuss.ocaml.org/u/yallop)
#### Post date: [June 4, 2020, 9:31am UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907/5 "2020-06-04T09:31:06Z")

</div>

Polymorphic variants aren’t defined. If you define two variants with the same constructors, like this:

```ocaml
type s = A | B
type t = A | B

```

then you end up with two incompatible types, since each variant definition creates a fresh type.

However, if you write something similar for polymorphic variants

```ocaml
type s = [`A | `B]
type t = [`A | `B]

```

then you haven’t created anything new: `s` and `t` are just aliases for equivalent type expressions.

---

<div class="post-metadata">

### Author: ![threepwood](https://avatars.discourse-cdn.com/v4/letter/t/8dc957/32.png) [@threepwood](https://discuss.ocaml.org/u/threepwood)
#### Post date: [June 4, 2020, 10:18am UTC](https://discuss.ocaml.org/t/module-type-and-enum-type/5907/6 "2020-06-04T10:18:48Z")

</div>

> [@Chimrod](#):
>
> But I do not understand the rationale behind this, as the polymorphic variants does not follow the same scheme.

If you ask why the manual says this even though polymorphic variants exist, it’s because that sentence is not talking about polymorphic variants I guess.

If you ask why variants and records behave that way: well, both behaviours are useful. Structural types (like objects and polymorphic variants) are more flexible and allow for nice tricks in various cases. Nominal types (like variants and records) are better-behaved; with nominal types, the type-checker tends to catch more bugs and give better error messages.
