# Aliasing functor's submodules

**URL:** <https://discuss.ocaml.org/t/aliasing-functors-submodules/14980>\
**Category:** Learning\
**Created:** [July 17, 2024, 2:27pm UTC](https://discuss.ocaml.org/t/aliasing-functors-submodules/14980 "2024-07-17T14:27:03Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![lastgenius](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/lastgenius/32/5190_2.png) [@lastgenius](https://discuss.ocaml.org/u/lastgenius)\
**Post date:** [July 17, 2024, 2:27pm UTC](https://discuss.ocaml.org/t/aliasing-functors-submodules/14980/1 "2024-07-17T14:27:03Z")

</div>

Is there a way to alias a submodule of a functor? (Not sure if I’m using the terminology correctly here)

This is allowed:

```auto
module StringHeap = Binary (String)
module Submodule = StringHeap.Submodule

```

These are not:

```auto
let module StringHeap = Binary (String) in (* Syntax error, let-extension with punning expected *)
module Submodule = StringHeap.Submodule

```

Or:

```auto
module Submodule = (Binary (String)).Submodule (* Syntax error *)

```

How do I achieve this if I only want to expose `Submodule` and not the module it comes from?  
One possible solution would be to factor out Submodule into its own functor, but I am interested in this particular way of achieving this without factoring it out.

Minimal example:  
funkt.ml:

```auto
module type OrderedType = sig
  type t

  val compare : t -> t -> int
  val empty : t
end

module type S = sig
  type t

  module Submodule : sig
    val func : unit -> bool
  end

  val empty : t
  val is_empty : t -> bool
end

module Binary (Elt : OrderedType) : S = struct
  type t = Elt.t

  module Submodule = struct
    let func = failwith "Not yet implemented"
  end

  let empty = failwith "Not yet implemented"
  let is_empty h = Elt.compare Elt.empty h = 0
end

module StringHeap = Binary (String)
module Submodule = StringHeap.Submodule

let () =
  print_endline (string_of_bool StringHeap.(is_empty empty));
  print_endline (string_of_bool (Submodule.func ()))

```

dune:

```auto
(executable
  (name funkt)
  (public_name funkt)
  (libraries str))

```

dune-project:

```auto
(lang dune 3.7)
(package (name funkt))

```

---

<div class="post-metadata">

**Author:** ![vlaviron](https://avatars.discourse-cdn.com/v4/letter/v/ec9cab/32.png) [@vlaviron](https://discuss.ocaml.org/u/vlaviron)\
**Post date:** [July 17, 2024, 2:58pm UTC](https://discuss.ocaml.org/t/aliasing-functors-submodules/14980/2 "2024-07-17T14:58:21Z")

</div>

Module aliases (i.e. re-exporting an existing module under a different name) cannot contain functor applications.  
The usual way to solve your issue is to define both modules in the implementation, but only export one of them in the interface (`.mli` file).  
If you don’t want to write an `.mli` file, you can use the following hack:

```ocaml
module Submodule = struct
  open! Binary(String)
  include Submodule
end

```

I agree that the error message isn’t great, and it would also be natural to allow `module M = F(X).N` directly (I don’t know if there are technical difficulties in implementing this feature).

---

<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:** [July 17, 2024, 3:03pm UTC](https://discuss.ocaml.org/t/aliasing-functors-submodules/14980/3 "2024-07-17T15:03:43Z")

</div>

You can use the generalized `open` to bring definitions from a module into scope without exporting them, like this:

```ocaml
module Submodule = struct
  open Binary (String)
  include Submodule
end

```

(although this will copy all the fields of `Submodule`, which is a bit wasteful), or like this:

```ocaml
include struct
  open Binary(String)
  module Submodule = Submodule
end

```

(which won’t copy the fields)
