# Structure the code in modules

**URL:** <https://discuss.ocaml.org/t/structure-the-code-in-modules/5401>\
**Category:** Learning\
**Tags:** module, dune\
**Created:** [March 29, 2020, 2:42pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401 "2020-03-29T14:42:29Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![sebbes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sebbes/32/1997_2.png) [@sebbes](https://discuss.ocaml.org/u/sebbes)\
**Post date:** [March 29, 2020, 2:42pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/1 "2020-03-29T14:42:30Z")

</div>

Hello,

I have troubles in splitting my app into modules & submodules using dune.

Here is my current project tree (following this SO answer: [ocaml - Running OUnit tests using dune - Stack Overflow](https://stackoverflow.com/a/53325230/3421913) ) :

```auto
├── dune
├── dune-project
├── booleanFormulae
│ ├── booleanFormulae.ml // begins with "open Types"
│ ├── booleanFormulae.mli // begins with "open Types"
│ ├── dune
│ ├── parser.ml // begins with "open Types"
│ └── types.ml
├── main.ml
├── test
│ ├── dune
│ └── test.ml

```

Here is the root dune file:

```auto
(executable
 (name main)
 (libraries BooleanFormulae))

```

Here is `lib/dune`:

```auto
(library 
    (name BooleanFormulae)
    (libraries angstrom)
    (preprocess (pps ppx_deriving.show ppx_deriving.ord)))

```

In the dune docs ([Stanza Reference — Dune documentation](https://dune.readthedocs.io/en/stable/dune-files.html)), it is said

> By default dune will use all the .ml/.re files in the same directory as the `dune` file.

So if I understand well, in the `main.ml` I should be able to `open BooleanFormulae.Parser` or  
`open BooleanFormulae.Types`.  
However, `dune build main.exe` complains:

```auto
File "main.ml", line 2, characters 5-27:
2 | open BooleanFormulae.Parser
         ^^^^^^^^^^^^^^^^^^^^^^
Error: Unbound module BooleanFormulae.Parser

```

Just referring to `Parser` in `main.ml` doesn’t work either.

What should I do? And is my project globally well structured?

---

<div class="post-metadata">

**Author:** ![sebbes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sebbes/32/1997_2.png) [@sebbes](https://discuss.ocaml.org/u/sebbes)\
**Post date:** [March 29, 2020, 2:51pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/2 "2020-03-29T14:51:25Z")

</div>

Related I think:

in the `test/test.ml`, I cannot refer to the values in `types.ml` (included in the `booleanFormulae.mli` interface) [Unbound constructor …], but I can do it in the `main.ml` file.

Here is my `test/dune`:

```auto
(test (name test) (libraries BooleanFormulae ounit2))

```

---

<div class="post-metadata">

**Author:** ![giltho](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/giltho/32/3521_2.png) [@giltho](https://discuss.ocaml.org/u/giltho)\
**Post date:** [March 29, 2020, 2:59pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/3 "2020-03-29T14:59:05Z")

</div>

I might be wrong, but the message is  
“unbound module BooleanFormulae.Parser”, not “unbound module BooleanFormulae”  
Can we see your booleanFormular.mli ?

But also, your library is called BooleanFormulae and your file is BooleanFormulae  
I’ve had issues with first letter case sensitivity in the past, try to have them matching

---

<div class="post-metadata">

**Author:** ![sebbes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sebbes/32/1997_2.png) [@sebbes](https://discuss.ocaml.org/u/sebbes)\
**Post date:** [March 29, 2020, 3:04pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/4 "2020-03-29T15:04:30Z")

</div>

Hi, thank you for trying to help. Change the case of my file to uppercase doesnt seem to get things better.

Here is my BooleanFormulae.mli:

```auto
open Types

type decTree = DecLeaf of bool | DecRoot of string * decTree * decTree
module VarsSet :
sig
(* set signature *)
end

val getVars : tformula -> VarsSet.t
type env 
val empty_env : env
val env_of_bindings : (string * bool) list -> env
val evalFormula : env -> tformula -> bool
val buildDecTree : tformula -> decTree

type bddGraph

val buildBdd : tformula -> bddGraph
val isTautology : tformula -> bool
val areEquivalent : tformula -> tformula -> bool
module Dot :
sig

  type style = Red | Dashed | Bold
  type elt = Node of (int * string) | Vertex of (int * int)

  type digraph

  val empty : digraph
  val join : digraph -> digraph -> digraph
  val addWithStyle : elt -> style list -> digraph -> digraph
  val add : elt -> digraph -> digraph
  val join_in_bracket : string list -> string
  val show : string -> digraph -> string
end
val bddToDot : bddGraph -> Dot.digraph
val decTreeToDot : int -> decTree -> int * Dot.digraph

```

---

<div class="post-metadata">

**Author:** ![giltho](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/giltho/32/3521_2.png) [@giltho](https://discuss.ocaml.org/u/giltho)\
**Post date:** [March 29, 2020, 3:40pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/5 "2020-03-29T15:40:23Z")

</div>

Ah ! I understand what’s happening now  
Didn’t read your tree properly

When you have a file in your directory that has the same name as your library (booleanFormulae here), dune creates a library from this file.  
Meaning, in booleanFormulae.ml you need:

```auto
module Parser = Parser

```

and in your booleanFormulae.mli you need

```auto
module Parser : sig
...
end

```

---

<div class="post-metadata">

**Author:** ![sebbes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sebbes/32/1997_2.png) [@sebbes](https://discuss.ocaml.org/u/sebbes)\
**Post date:** [March 29, 2020, 7:12pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/6 "2020-03-29T19:12:43Z")

</div>

Thank you, problem solved for the `BooleanFormulae.Parser`. I still have an issue with the tests:

```auto
$ dune runtest
File "test/test.ml", line 4, characters 9-12:
4 | let p1 = Var "P1"
             ^^^
Error: Unbound constructor Var

```

(Var is one of the constructors of `tformula` which is defined in `booleanFormulae/types.ml`. It is however accessible in `main.ml`)

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [March 30, 2020, 2:11am UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/7 "2020-03-30T02:11:30Z")

</div>

Does it work if you prefix the constructor with its module name: `BooleanFormulae.Types.Var`?

---

<div class="post-metadata">

**Author:** ![giltho](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/giltho/32/3521_2.png) [@giltho](https://discuss.ocaml.org/u/giltho)\
**Post date:** [March 30, 2020, 11:44am UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/8 "2020-03-30T11:44:49Z")

</div>

Careful, open != include, in your mli you open Types, but you don’t include it, so it will not be exported  
Unless you fixed it afterwards ?

---

<div class="post-metadata">

**Author:** ![sebbes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sebbes/32/1997_2.png) [@sebbes](https://discuss.ocaml.org/u/sebbes)\
**Post date:** [March 30, 2020, 1:00pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/9 "2020-03-30T13:00:11Z")

</div>

Thank you @yawaramin, but it doesn’t fix the issue…

@giltho I’ve tried to `include Types` instead of `open Types` in `booleanFormulae.mli`, but I have an “unbounded module type Types”:

```auto
File "BooleanFormulae/booleanFormulae.mli", line 2, characters 8-13:
2 | include Types
            ^^^^^
Error: Unbound module type Types

```

---

<div class="post-metadata">

**Author:** ![giltho](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/giltho/32/3521_2.png) [@giltho](https://discuss.ocaml.org/u/giltho)\
**Post date:** [March 30, 2020, 2:30pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/10 "2020-03-30T14:30:34Z")

</div>

`include Types` doesn’t work but `open Types` does ? that doesn’t sound right

---

<div class="post-metadata">

**Author:** ![yawaramin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/yawaramin/32/3384_2.png) [@yawaramin](https://discuss.ocaml.org/u/yawaramin)\
**Post date:** [March 30, 2020, 3:11pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/11 "2020-03-30T15:11:47Z")

</div>

I think it would be helpful if you could upload a small sample project with this issue. We could examine it and figure out what should be changed to make it work.

---

<div class="post-metadata">

**Author:** ![sebbes](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sebbes/32/1997_2.png) [@sebbes](https://discuss.ocaml.org/u/sebbes)\
**Post date:** [March 30, 2020, 3:31pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/12 "2020-03-30T15:31:44Z")

</div>

Yes, I think it will be simpler.

Here is the project [https://github.com/sebsheep/decision\_tree](https://github.com/sebsheep/decision_tree)

I don’t know how yet to specify what package install with opam (like the “requirements.txt” in python or “package.json” with npm). The dependencies are: ounit2 and angstrom.

thank you for your time!

---

<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 31, 2020, 8:10am UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/13 "2020-03-31T08:10:39Z")

</div>

> [@giltho](#):
>
> `include Types` doesn’t work but `open Types` does ? that doesn’t sound right

That’s in a `.mli` file. To include the contents of another module, the corresponding signature item is `include module type of Types`. To expand a bit on this:

- `Types` is a module.
- its (inferred) module type is `module type of Types`
- in mli files, `include` expects a module type (which does not necessarily correspond to a module in particular, which is why you can do `include Set.OrderedType`)

---

<div class="post-metadata">

**Author:** ![giltho](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/giltho/32/3521_2.png) [@giltho](https://discuss.ocaml.org/u/giltho)\
**Post date:** [March 31, 2020, 9:47am UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/14 "2020-03-31T09:47:03Z")

</div>

Ah it’s in the mli didn’t catch that indeed !

---

<div class="post-metadata">

**Author:** ![chrisnevers](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/chrisnevers/32/1854_2.png) [@chrisnevers](https://discuss.ocaml.org/u/chrisnevers)\
**Post date:** [April 10, 2020, 7:07pm UTC](https://discuss.ocaml.org/t/structure-the-code-in-modules/5401/15 "2020-04-10T19:07:41Z")

</div>

Additionally, you can change

```auto
(library 
    (name BooleanFormulae)
    (libraries angstrom)
    (preprocess (pps ppx_deriving.show ppx_deriving.ord)))

```

to

```auto
(library 
    (name BooleanFormulae)
    (libraries angstrom)
    (modules parser types)
    (preprocess (pps ppx_deriving.show ppx_deriving.ord)))

```

to be able to access `BooleanFormulae.Parser` from `main.ml`.
