# Combining independent extension functors

**URL:** https://discuss.ocaml.org/t/combining-independent-extension-functors/6483
**Category:** Learning
**Tags:** module, functor
**Created:** [September 23, 2020, 10:09am UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483 "2020-09-23T10:09:39Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![bbc2](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bbc2/32/807_2.png) [@bbc2](https://discuss.ocaml.org/u/bbc2)
#### Post date: [September 23, 2020, 10:09am UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483/1 "2020-09-23T10:09:39Z")

</div>

I’m trying to make independent functors that take a module as argument and return a similar module with a new value. I’d like to be able to chain such functors in a way that keeps the contribution of each one without having to define signatures for each possible combination.

I guess that could also be seen as a kind of polymorphism for module signatures. Anyway, here’s an example to clarify what I mean:

```ocaml
module type X = sig
  val x : int
end

module Extend_with_y(M : X) = struct
  include M

  let y = 2
end

module Extend_with_z(M : X) = struct
  include M

  let z = 3
end

module A = struct
  let x = 1
end
module B = Extend_with_y(A)
module C = Extend_with_z(B)

let () =
  Printf.printf "%d, %d, %d\n" C.x C.y C.z

```

Currently, this results in:

```auto
File "ocaml_sig_param.ml", line 25, characters 35-38:
25 | Printf.printf "%d, %d, %d\n" C.x C.y C.z
                                        ^^^
Error: Unbound value C.y

```

I would like to make it work by keeping `Extend_with_y` and `Extend_with_z` independent. `Extend_with_z` would have a signature like `(M : sig include X + other things end) -> sig include X val z : int + those other things end`, so that it reexports what other types or values of `M` instead of erasing them and only keeping `x` and `z`.

Is it possible? Would it even make sense for OCaml to provide such a behavior? It’s possible that I’m missing something completely obvious, since I haven’t really used functors extensively during the last few months.

---

<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: [September 23, 2020, 10:52am UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483/2 "2020-09-23T10:52:18Z")

</div>

I don’t think functors would be the right choice here.  
What about :

```auto
module A : X = 
  let x = 1
end

module With_z = struct
  let z = 3
end

module With_y = struct
  let y = 2
end

module C = struct
   include A
   include With_y
   include With_z
end

```

Now one reason you might want a functor could be that the value you’re adding to the module depends on what’s inside the module, but it still works

```auto
module With_y (A: X) = 
   let y = f a (* f is whatever operation you want *)
end

module C = struct 
   include A
   include With_y(A)
end

```

I agree it’s a bit more verbose, but to my knowledge (which is not exhaustive on OCaml), there is no way to do this with functors

---

<div class="post-metadata">

### Author: ![bbc2](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bbc2/32/807_2.png) [@bbc2](https://discuss.ocaml.org/u/bbc2)
#### Post date: [September 23, 2020, 11:04am UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483/3 "2020-09-23T11:04:41Z")

</div>

I indeed need the functors, for reasons not shown in the example. In reality, I’m extending something like `Set.Make` but showing that in the example would have made it too complex.

I believe the second solution would work. To come back to my example, I could write:

```ocaml
module C = struct
  include Extend_with_y(A)
  include Extend_with_z(A)
end

```

And if I simplify the functors to only export what they create, I just have to prepend `include A` in the definition of `C`. Sounds like a good solution to me.

---

<div class="post-metadata">

### Author: ![malva](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/malva/32/2233_2.png) [@malva](https://discuss.ocaml.org/u/malva)
#### Post date: [September 23, 2020, 4:03pm UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483/4 "2020-09-23T16:03:02Z")

</div>

I was thinking about how to implement this and came up with the following code

```auto
module type MTy = 
sig 
  module type T 
end

module Extend_x(Ty : MTy)(M : Ty.T) =
struct
  include M
      
  let x = 2
end
                                      

module Extend_y(Ty : MTy)(M : Ty.T) =
struct
  include M
      
  let y = 3
end

module Base = 
struct 
  let a = 1
end

module M1 = Extend_x(struct module type T = module type of Base end)(Base)
module M2 = Extend_y(struct module type T = module type of M1 end)(M1)
    
let result = M2.a + M2.x + M2.y

```

I was somewhat surprised to discover that this code, which I thought would be valid, actually fails to compile since OCaml seems to demand that `include` directives must only refer to modules whose module type is known (i.e. not a module type variable). This seems like a big restriction and I was wondering whether it’s in place because of fundamental limitations or simply because there’s no demand for it.

---

<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: [September 23, 2020, 6:31pm UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483/5 "2020-09-23T18:31:34Z")

</div>

Rather than copying the whole module every time (and yes `include` is a copy) another option is to implement extensions that only add the new features and compose those extensions:

```ocaml
module type X = sig val x : int end

module Extend_with_y(M : X) = struct
  let y = 2
end

module Extend_with_z(M : X) = struct
  let z = 3
end

module A = struct
  let x = 1
end
module B = struct
  include A
  include Extend_with_y(A)
end
module C = struct
  include B
  include Extend_with_z(B)
end
let () =
  Printf.printf "%d, %d, %d\n" C.x C.y C.z

```

Including abstract module type does not work because `include` is not part of the module type system: it merely inlines the content of the signature. Being able to include any module with a statistically unknown number of elements would break the compilation of functors. It is also unclear what should happen in this situation in term of scope or binding in

```ocaml
let x = 1
include M
let y = x + 1

```

if it is not known if `M` contains `x` or not.

Similarly, depending on `TX` and `TY`

```auto
module type S = sig
  include TX
  include TY
end

```

is not always valid.

---

<div class="post-metadata">

### Author: ![bbc2](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bbc2/32/807_2.png) [@bbc2](https://discuss.ocaml.org/u/bbc2)
#### Post date: [September 23, 2020, 8:20pm UTC](https://discuss.ocaml.org/t/combining-independent-extension-functors/6483/6 "2020-09-23T20:20:36Z")

</div>

Thanks for the clarification. I think I see why implementing what I was initially suggesting would cause issues.
