# Functors vs First Class Modules

**URL:** <https://discuss.ocaml.org/t/functors-vs-first-class-modules/1722>\
**Category:** Learning\
**Created:** [March 16, 2018, 7:06am UTC](https://discuss.ocaml.org/t/functors-vs-first-class-modules/1722 "2018-03-16T07:06:33Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ifazk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ifazk/32/836_2.png) [@ifazk](https://discuss.ocaml.org/u/ifazk)\
**Post date:** [March 16, 2018, 7:06am UTC](https://discuss.ocaml.org/t/functors-vs-first-class-modules/1722/1 "2018-03-16T07:06:33Z")

</div>

Is there anything that can be done with functors that cannot be done with functions that manipulate modules?

At a first look, it seems functions are strictly more powerful since they can accept both modules and values as arguments.

---

<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:** [March 16, 2018, 8:42am UTC](https://discuss.ocaml.org/t/functors-vs-first-class-modules/1722/2 "2018-03-16T08:42:04Z")

</div>

> [@ifazk](#):
>
> Is there anything that can be done with functors that cannot be done with functions that manipulate modules?

Yes, you can abstract over parametric type with functors but not with first-class modules.

```ocaml
module type MAPABLE = sig
  type 'a t
  val map : ('a -> 'b) -> 'a t -> 'b t
end

module F
(M : MAPABLE) 
(Param : sig type a type b val f : a -> b val x : a M.t end) = struct
  let res = M.map Param.f Param.x
end

module M = F (struct include List type 'a t = 'a list end)
(struct type a = int type b = string let f = string_of_int let x = [1; 2; 3] end)

module N = F (struct include Array type 'a t = 'a array end)
(struct type a = int type b = string let f = string_of_int let x = [|1; 2; 3|] end)

M.res;;
- : string list = ["1"; "2"; "3"]

N.res;;
- : string array = [|"1"; "2"; "3"|]

```

---

<div class="post-metadata">

**Author:** ![ifazk](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/ifazk/32/836_2.png) [@ifazk](https://discuss.ocaml.org/u/ifazk)\
**Post date:** [March 16, 2018, 6:51pm UTC](https://discuss.ocaml.org/t/functors-vs-first-class-modules/1722/3 "2018-03-16T18:51:10Z")

</div>

It was a good exercise to try to replicate the above functor with a function and seeing where things go wrong.

Thanks!

---

<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:** [March 16, 2018, 8:21pm UTC](https://discuss.ocaml.org/t/functors-vs-first-class-modules/1722/4 "2018-03-16T20:21:18Z")

</div>

Note that with the experimental extension [modular implicits](https://github.com/ocamllabs/ocaml-modular-implicits), you can write this examples with plain functions (under the hood, functions with implicit parameters are implemented as first-class functors).

```ocaml
module type Map = sig type 'a t val map : ('a -> 'b) -> 'a t -> 'b t end

(* note the keyword `implicit' when you declare a module *)
implicit module Map_list = struct type 'a t = 'a list let map = List.map end

implicit module Map_array = struct type 'a t = 'a array let map = Array.map end

(* implicit module parameter must be put into curly braces *)
let map {M : Map} f x = M.map f x;;
val map : {M : Map} -> ('a -> 'b) -> 'a M.t -> 'b M.t = <fun>

map string_of_int [1; 2; 3];;
- : string Map_list.t = ["1"; "2"; "3"]

map string_of_int [|1; 2; 3|];;
- : string Map_array.t = [|"1"; "2"; "3"|]

```
