# Reducing duplicate code in modules with parameterized type

**URL:** <https://discuss.ocaml.org/t/reducing-duplicate-code-in-modules-with-parameterized-type/13446>\
**Category:** Learning\
**Tags:** module, functor, first-class\_modules\
**Created:** [November 17, 2023, 12:52pm UTC](https://discuss.ocaml.org/t/reducing-duplicate-code-in-modules-with-parameterized-type/13446 "2023-11-17T12:52:30Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![cpa](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/cpa/32/4866_2.png) [@cpa](https://discuss.ocaml.org/u/cpa)\
**Post date:** [November 17, 2023, 12:52pm UTC](https://discuss.ocaml.org/t/reducing-duplicate-code-in-modules-with-parameterized-type/13446/1 "2023-11-17T12:52:30Z")

</div>

Hello,  
I found myself writing the following piece of code, and I’m wondering how can I reuse more code and not repeat re-declaring `type expr = ...` in both modules (since outside of this minimal example this would be a large grammar and repeating it twice or even more times would be bad).

```auto
module SimpleAST = struct 
  type 'a ast_node = 'a
  type expr = Bool of bool ast_node | Int of int ast_node
  (* more type definitions shared between SimpleAST and TypedAST *)
  (* ... *)
end

module TypedAST = struct 
  type 'a ast_node = {node: 'a; type_info: TType} (* everything is the same except the definion of ast_node *)
  type expr = Bool of bool ast_node | Int of int ast_node
  (* more type definitions shared between SimpleAST and TypedAST *)
  (* ... *)
end

```

Ultimately, what I’m trying to achieve is having tree variatinons which represent the same structure (e.g. an `expr` will always have as children a `Bool` and an `Int` across all variations, but the actual nodes of each tree to be of different type)

Also, the reason I am not creating a signature for both modules is that I want the definitions of `expr` etc to be public, so if I had a type module I would have to triplicate the definitions. As a result this is preventing me from using functors (but possibly there’s something I’m missing here).

Is there any way to achieve that or factor out the redundant code above? Thanks!

---

<div class="post-metadata">

**Author:** ![thierry-martinez](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/thierry-martinez/32/1481_2.png) [@thierry-martinez](https://discuss.ocaml.org/u/thierry-martinez)\
**Post date:** [November 17, 2023, 1:06pm UTC](https://discuss.ocaml.org/t/reducing-duplicate-code-in-modules-with-parameterized-type/13446/2 "2023-11-17T13:06:52Z")

</div>

You may introduce a `module type` just for parameterizing by `ast_node`, without duplicating the definition of `expr`.

```auto
module type Ast_node = sig
  type 'a t
end

module MakeAST (Ast_node : Ast_node) = struct
  type expr = Bool of bool Ast_node.t | Int of int Ast_node.t
  (* more type definitions shared between SimpleAST and TypedAST *)
end

module SimpleAST = struct 
  type 'a ast_node = 'a
  include MakeAST (struct type 'a t = 'a ast_node end)
  (* ... *)
end

module TypedAST = struct 
  type 'a ast_node = {node: 'a; type_info: ttype} (* everything is the same except the definion of ast_node *)
  include MakeAST (struct type 'a t = 'a ast_node end)
  (* ... *)
end

```

---

<div class="post-metadata">

**Author:** ![JohnJ](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/johnj/32/6020_2.png) [@JohnJ](https://discuss.ocaml.org/u/JohnJ)\
**Post date:** [November 17, 2023, 2:03pm UTC](https://discuss.ocaml.org/t/reducing-duplicate-code-in-modules-with-parameterized-type/13446/3 "2023-11-17T14:03:33Z")

</div>

Another option is to make `expr` a type constructor and then reuse it with each of your other types.

```ocaml
type ('bool, 'int) generic_expr = Bool of 'bool | Int of 'int

module SimpleAST = struct 
  type 'a ast_node = 'a
  type expr = (bool ast_node, int ast_node) generic_expr
end

module TypedAST = struct 
  type 'a ast_node = {node: 'a; type_info: TType.t}
  type expr = (bool ast_node, int ast_node) generic_expr
end

```

---

<div class="post-metadata">

**Author:** ![micahcantor](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/micahcantor/32/4590_2.png) [@micahcantor](https://discuss.ocaml.org/u/micahcantor)\
**Post date:** [November 18, 2023, 4:25am UTC](https://discuss.ocaml.org/t/reducing-duplicate-code-in-modules-with-parameterized-type/13446/4 "2023-11-18T04:25:18Z")

</div>

This is interesting, I don’t think I’ve seen this approach before. Only problem I see is that for a “real” AST with say 20 variants, applying each as a type parameter would be pretty unwieldy. But for a small type like this it works nicely.
