# Open vs include?

**URL:** <https://discuss.ocaml.org/t/open-vs-include/12289>\
**Category:** Learning\
**Created:** [June 1, 2023, 8:00am UTC](https://discuss.ocaml.org/t/open-vs-include/12289 "2023-06-01T08:00:14Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zeroexcuses/32/1692_2.png) [@zeroexcuses](https://discuss.ocaml.org/u/zeroexcuses)\
**Post date:** [June 1, 2023, 8:00am UTC](https://discuss.ocaml.org/t/open-vs-include/12289/1 "2023-06-01T08:00:14Z")

</div>

Code: (from [OCaml - The module system](https://v2.ocaml.org/releases/5.0/htmlman/moduleexamples.html#sec20) )

```auto
  module PrioQueue = struct
    type priority = int
    type 'a queue = Empty | Node of priority * 'a * 'a queue * 'a queue

    let empty = Empty

    let rec insert queue prio elt =
      match queue with
      | Empty -> Node (prio, elt, Empty, Empty)
      | Node (p, e, left, right) ->
          if prio <= p then Node (prio, elt, insert right p e, left) else Node (p, e, insert right prio elt, left)

    exception Queue_is_empty

    let rec remove_top = function
      | Empty -> raise Queue_is_empty
      | Node (_prio, _elt, left, Empty) -> left
      | Node (_prio, _elt, Empty, right) -> right
      | Node (_prio, _elt, (Node (lprio, lelt, _, _) as left), (Node (rprio, relt, _, _) as right)) ->
          if lprio <= rprio then Node (lprio, lelt, remove_top left, right)
          else Node (rprio, relt, left, remove_top right)

    let extract = function
      | Empty -> raise Queue_is_empty
      | Node (prio, elt, _, _) as queue -> (prio, elt, remove_top queue)
  end

  module PrioQueueOpt = struct
    include PrioQueue

    let remove_top_ot x = try Some (remove_top x) with Queue_is_empty -> None
    let extract_opt x = try Some (extract x) with Queue_is_empty -> None
  end

```

This code compiles regardless of whether I use `include PrioQueue` or `open PrioQueue`.

My current (possibly incorrect) understanding is:

1. `open` adds bindings to local env referencing openeed module
2. `include` literally copies over the code

I regularly use `open`. I have seen code with `include`, but I don’t think  
I have ever used it myself.

What are situations where `open` is not sufficient and we have to use `include` ?

---

<div class="post-metadata">

**Author:** ![vds](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/vds/32/2013_2.png) [@vds](https://discuss.ocaml.org/u/vds)\
**Post date:** [June 1, 2023, 8:29am UTC](https://discuss.ocaml.org/t/open-vs-include/12289/2 "2023-06-01T08:29:02Z")

</div>

One important observable difference is that `include` re-exports what’s included, not `open`.

For example:

```auto
  ...

  module PrioQueueOpt = struct
    include PrioQueue

    let remove_top_ot x = try Some (remove_top x) with Queue_is_empty -> None
  end

  let new_queue = PrioQueueOpt.empty (* works ok *)

```

```auto
  ...

  module PrioQueueOpt = struct
    open PrioQueue

    let remove_top_ot x = try Some (remove_top x) with Queue_is_empty -> None
  end

  let new_queue = PrioQueueOpt.empty (* fail because [empty] is not re-exported by PrioQueue *)

```

---

<div class="post-metadata">

**Author:** ![AsimovIV](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/asimoviv/32/4162_2.png) [@AsimovIV](https://discuss.ocaml.org/u/AsimovIV)\
**Post date:** [June 2, 2023, 5:46am UTC](https://discuss.ocaml.org/t/open-vs-include/12289/3 "2023-06-02T05:46:07Z")

</div>

It is also explained [here.](https://courses.cs.cornell.edu/cs3110/2021sp/textbook/modules/include_vs_open.html)

---

<div class="post-metadata">

**Author:** ![zeroexcuses](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zeroexcuses/32/1692_2.png) [@zeroexcuses](https://discuss.ocaml.org/u/zeroexcuses)\
**Post date:** [June 2, 2023, 6:38am UTC](https://discuss.ocaml.org/t/open-vs-include/12289/4 "2023-06-02T06:38:26Z")

</div>

@AsimovIV@vds :

Thanks! Is this (re-exporting of defs) the only difference? I thought there was something deeper / more subtle going on.

---

<div class="post-metadata">

**Author:** ![zbaylin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zbaylin/32/4047_2.png) [@zbaylin](https://discuss.ocaml.org/u/zbaylin)\
**Post date:** [June 2, 2023, 2:13pm UTC](https://discuss.ocaml.org/t/open-vs-include/12289/5 "2023-06-02T14:13:47Z")

</div>

From the OCaml manual: [Including the components of another structure](https://v2.ocaml.org/manual/modules.html#sss:mexpr-include)

> The difference between `open` and `include` is that `open` simply provides short names for the components of the opened structure, without defining any components of the current structure, while `include` also adds definitions for the components of the included structure.

So yes, that seems to be the only difference between the two. I haven’t seen any in practice either.

---

<div class="post-metadata">

**Author:** ![zbaylin](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/zbaylin/32/4047_2.png) [@zbaylin](https://discuss.ocaml.org/u/zbaylin)\
**Post date:** [June 2, 2023, 2:28pm UTC](https://discuss.ocaml.org/t/open-vs-include/12289/6 "2023-06-02T14:28:16Z")

</div>

To answer this part of your question, though:

> What are situations where `open` is not sufficient and we have to use `include` ?

In my experience, `include` is usually used when some kind of subtyping/inheritance is desired. For example, if I have some module signatures:

```ocaml
module type TO_STRING = sig
  type t
  val to_string : t -> string
end

module type OF_STRING = sig
  type t
  val of_string : string -> t option
end

module type SERIALIZABLE = sig
  include TO_STRING
  include OF_STRING with type t := t
end

```

In an OOP context, the closest analogue might be a class that implements two interfaces. But here you might use it like this:[TryOCaml](https://try.ocamlpro.com/#code/module'type'TO_STRING'='sig!type't!val'to_string':'t'-$.'string!end!!module'type'OF_STRING'='sig!type't!val'of_string':'string'-$.'t'option!end!!module'type'SERIALIZABLE'='sig!include'TO_STRING!include'OF_STRING'with'type't':='t!end!!module'Int_serializable'='struct!type't'='int!let'to_string'='string_of_int!let'of_string'='int_of_string_opt!end!!module'_':'TO_STRING'='Int_serializable'(*'Won$,t'compile'if'$/Int_serializable$1'doesn$,t'conform'to'$/TO_STRING$1'*)!module'_':'OF_STRING'='Int_serializable!module'_':'SERIALIZABLE'='Int_serializable)

```ocaml
module Int_serializable = struct
  type t = int
  let to_string = string_of_int
  let of_string = int_of_string_opt
end

module _ : TO_STRING = Int_serializable (* Won't compile if [Int_serializable] doesn't conform to [TO_STRING] *)
module _ : OF_STRING = Int_serializable
module _ : SERIALIZABLE = Int_serializable

```

Obviously this is in the context of module signatures and not structures, but you can play around with this using structure-based `include`s and get the same result.
