# Compose complex struct signature

**URL:** <https://discuss.ocaml.org/t/compose-complex-struct-signature/13699>\
**Category:** Learning\
**Created:** [December 22, 2023, 3:20am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699 "2023-12-22T03:20:48Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Tom\_H](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@Tom\_H](https://discuss.ocaml.org/u/Tom_H)\
**Post date:** [December 22, 2023, 3:20am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/1 "2023-12-22T03:20:48Z")

</div>

Hi there, I am wondering if I can pass a type in signature declaration, so I can declare a return signature of a functor more clearly.

For example

```auto
module type Flour = sig
  type t
end

module type Bread = sig
  type t
end

module Cook (F : Flour) : Bread = struct
  type t = {material : F.t; sauce : 'a}
  let cook (material: F.t) sauce = {material; sauce}
end

```

For some reasons, I need to declare the return signature of functor `Cook` explicitly. However, I have no idea how to declare `cook` function in signature `Bread`. Can I declare/reference a type from another signature when declaring a new signature? Something like

```auto
module type Bread = sig
  type t
  type r = Flour.t
  val cook : r -> 'a -> t
end

```

---

<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:** [December 22, 2023, 3:47am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/2 "2023-12-22T03:47:02Z")

</div>

This should work:

```auto
module type Bread = sig
  type flour
  type 'a t = { material : flour; sauce : 'a }

  val cook : flour -> 'a -> 'a t
end

```

You can see this technique (a helper type) being used here: [OCaml library : Set](https://v2.ocaml.org/api/Set.html#MODULEMake) and [OCaml library : Set.S](https://v2.ocaml.org/api/Set.S.html#TYPEelt)

---

<div class="post-metadata">

**Author:** ![Tom\_H](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@Tom\_H](https://discuss.ocaml.org/u/Tom_H)\
**Post date:** [December 22, 2023, 4:30am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/3 "2023-12-22T04:30:14Z")

</div>

Thank you for your reply! It works!

---

<div class="post-metadata">

**Author:** ![Tom\_H](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@Tom\_H](https://discuss.ocaml.org/u/Tom_H)\
**Post date:** [December 22, 2023, 5:50am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/4 "2023-12-22T05:50:39Z")

</div>

I have complete my code, it looks like this. Notice that instead of using `'a`, I replaced it with a explicit type.

```auto
module type Flour = sig
  type t
end

module type Bread = sig
  type i
  type t

  val cook : i -> int -> t
end

module Cook (F : Flour) : Bread = struct
  type i = F.t

  type t =
    { material : i
    ; cid : int
    }

  let cook (material : i) cid = { material; cid }
end

module F1 = struct
  type t = { fid : int }
end

module B1 = Cook (F1)

let f1 : F1.t = { fid = 3 }
let b1 = B1.cook f1 3

```

However, the last line does not work, it says

```auto
This expression has type F1.t but an expression was expected of type B1.i
type t = { fid : int; }

```

In fact, `F1.t` and `B1.i` are of the same type, because `B1` is created through `Cook` functor. Is there anything i am missing? Or do I misunderstand something 🙁

---

<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:** [December 22, 2023, 6:22am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/5 "2023-12-22T06:22:45Z")

</div>

Yes, you are making the `Cook` functor’s output module too abstract, so the compiler ‘forgets’ the fact that the types are the same. The simplest way to solve it is to just not annotate the return type:

```auto
module Cook(F : Flour) = struct
  ...
end

```

In that case the compiler will infer the correct type and understand the type relationships automatically.

---

<div class="post-metadata">

**Author:** ![kantian](https://avatars.discourse-cdn.com/v4/letter/k/4bbf92/32.png) [@kantian](https://discuss.ocaml.org/u/kantian)\
**Post date:** [December 22, 2023, 6:33am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/6 "2023-12-22T06:33:46Z")

</div>

> [@Tom\_H](#):
>
> In fact, `F1.t` and `B1.i` are of the same type, because `B1` is created through `Cook` functor. Is there anything i am missing?

When you have a signature with abstract type, you can make it less abstract adding equation with `with type t =` expression. For instance you can specialize your `Bread` signature with `type i = float`.

```ocaml
module type Bread_with_float = Bread with type i = float;;
module type Bread_with_float =
  sig type i = float type t val cook : i -> int -> t end

```

And so, you should write your functor signature:

```ocaml
module Cook (F : Flour) : Bread with type i = F.t = struct
  ...
end

```

This way you will have the equation `F1.t = B1.i`

---

<div class="post-metadata">

**Author:** ![Tom\_H](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@Tom\_H](https://discuss.ocaml.org/u/Tom_H)\
**Post date:** [December 22, 2023, 6:35am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/7 "2023-12-22T06:35:07Z")

</div>

Thank you for your solution! This is a simplified version of my code. In my original code, it is way more complex. The type of `Flour` can have variant from `Cook(Flour)`. In this case, when I need to generate the new module through functor, I need to explicit provide the return signature for it because they are mutually referred.

---

<div class="post-metadata">

**Author:** ![Tom\_H](https://avatars.discourse-cdn.com/v4/letter/t/5e9695/32.png) [@Tom\_H](https://discuss.ocaml.org/u/Tom_H)\
**Post date:** [December 22, 2023, 6:37am UTC](https://discuss.ocaml.org/t/compose-complex-struct-signature/13699/8 "2023-12-22T06:37:18Z")

</div>

Thank you for your solution! It works! Many thanks! 😄
