Here’s a use-case for a recursive functor. I don’t know whether this is convincing as a case to add them to the language, since there seems to be a workaround. But I don’t really understand why the workaround works: it seems that recursive functors *are* allowed as long as the recursive functor call isn’t ever named or opened, but it can be referred to inline in a type definition. Is that intentional?

Suppose I have a functor defined elsewhere (like in someone else’s library that I can’t modify), for example:

```
module type Type = sig type t end
module Pair (T : Type) = struct type t = T.t * T.t end
```

I want to define a new type that recursively involves `Pair`

of itself. I can do this with an ordinary recursive module (this is the main reason I ever use recursive modules):

```
module rec Foo1 : sig
type t
end = struct
module P = Pair(Foo1)
type t = Zero | Suc of P.t
end
```

Now suppose I want my new type to also be parametrized over some other type in a functor. If I straightforwardly convert `Foo1`

into a functor, I get the “unsafe functor” error:

```
module rec Foo2 : functor (T : Type) -> sig
type t
end = functor (T : Type) -> struct
module P = Pair(Foo2(T))
type t = Zero of T.t | Suc of P.t
end
--> Module Foo2 defines an unsafe functor, Foo2
```

It seems to be possible to avoid this error by doing the functor application inline rather than declaring the module `P`

first, i.e. this works:

```
module rec Foo3 : functor (T : Type) -> sig
type t
end = functor (T : Type) -> struct
type t = Zero of T.t | Suc of Pair(Foo3(T)).t
end
```

Next suppose `Foo`

also needs to define functions recursively on `t`

. The naive way to do this gives a different error:

```
module rec Foo4 : functor (T : Type) -> sig
type t
val to_int : t -> int
end = functor (T : Type) -> struct
type t = Zero of T.t | Suc of Pair(Foo4(T)).t
let rec to_int : t -> int = function Zero _ -> 0 | Suc (x,_) -> to_int x + 1
end
-> Error: This expression has type Foo4(T).t
but an expression was expected of type t
```

I assume what’s happening here is that the current module hasn’t been identified with its recursive call yet, so the compiler doesn’t know that `t`

is the same type as `Foo4(T).t`

. We can fix this by calling the version of `to_int`

in `Foo4(T)`

rather than the current module. But we can’t write `Foo4(T).to_int`

, so we need to declare `Foo4(T)`

as a local module, and then we get the same unsafe functor error:

```
module rec Foo5 : functor (T : Type) -> sig
type t
val to_int : t -> int
end = functor (T : Type) -> struct
type t = Zero of T.t | Suc of Pair(Foo5(T)).t
let to_int : t -> int = function
| Zero _ -> 0
| Suc (x,_) -> let module F = Foo5(T) in F.to_int x + 1
end
--> Module Foo5 defines an unsafe functor, Foo5.
```

Finally, this can be worked around by defining two separate functors, one recursive one for the type and another nonrecursive one to add the functions:

```
module rec InternalFoo : functor (T : Type) -> sig
type t = Zero of T.t | Suc of Pair(InternalFoo(T)).t
end = functor (T : Type) -> struct
type t = Zero of T.t | Suc of Pair(InternalFoo(T)).t
end
module Foo6 (T : Type) : sig
type t
val to_int : t -> int
end = struct
include InternalFoo(T)
let rec to_int : t -> int = function
| Zero _ -> 0
| Suc (x, _) -> to_int x + 1
end
```

This is a bit more boilerplate, though perhaps not that bad. But I don’t understand why it works, and I do think it would be more intuitive if `Foo2`

and `Foo5`

could work directly.