# Base: design of empty in Map/Set/Hashtbl

**URL:** https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932
**Category:** Learning
**Created:** [April 12, 2023, 12:51am UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932 "2023-04-12T00:51:33Z")
**Posts on this page:** 6
**Page:** 1

<div class="post-metadata">

### Author: ![bufordrat](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bufordrat/32/4028_2.png) [@bufordrat](https://discuss.ocaml.org/u/bufordrat)
#### Post date: [April 12, 2023, 12:51am UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932/1 "2023-04-12T00:51:33Z")

</div>

Hello all,

Currently working through the awesomely fun _Real World OCaml_, 2nd ed., which, among other things, is introducing me to the `Base` library. (Normally I use a different standard library.)

I noticed that `Base` defines these `empty`-making functions with “comparator module” inputs for `Set`/`Map`/`Hashtbl`/etc. E.g. `Base` wants you to do this:

```auto
utop[6]> open Base;;
utop[7]> module Dict = Map.M (String);;
module Dict :
  sig type nonrec 'v t = (string, 'v, String.comparator_witness) Map.t end
utop[8]> let empty = Map.empty (module String);;
val empty : (string, 'a, String.comparator_witness) Map.t = <abstr>

```

As opposed to what I think of as the normal `Stdlib`-y way to do it, which is to grab the `empty` value out of the module you defined via the `Map.Make` module functor:

```auto
utop[5]> module Dict = Stdlib.Map.Make (String);;

...etc...

utop[6]> let empty = Dict.empty;;
val empty : 'a Dict.t = <abstr>

```

I was wondering what the design rationale behind that is. If Jane Street is doing it, lol, it’s pretty much guaranteed there’s a compelling reason. Yet I can’t think of a reason to design `empty` in that way across all these modules, off the top of my head.

Thanks as always!

---

<div class="post-metadata">

### Author: ![TyOverby](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/tyoverby/32/2213_2.png) [@TyOverby](https://discuss.ocaml.org/u/TyOverby)
#### Post date: [April 12, 2023, 1:49am UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932/2 "2023-04-12T01:49:10Z")

</div>

Base and Core nudge you in the direction of the functorless approach because we found that big functors (`Comparable.Make` was the main one) were a cause of code bloat and slower compile times. I think I remember hearing that 30% time spent in the typechecker was spent comparing module signatures generated by `Comparable.Make`, `Map.Make` and its ilk. Now, most of the improvement was by getting rid of accessor functions, (e.g. `My_type.Map.find`), and `Core` still includes the functors and exports the `empty` value, but that’s mostly for backwards compatibility concerns (the values produced by successive calls to the `empty` function will yield physically different empty maps, but the `empty` value yielded by the `Make` functor is a singleton value)

---

<div class="post-metadata">

### Author: ![bufordrat](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bufordrat/32/4028_2.png) [@bufordrat](https://discuss.ocaml.org/u/bufordrat)
#### Post date: [April 12, 2023, 1:57am UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932/3 "2023-04-12T01:57:23Z")

</div>

Fascinating. So would you say there has been slash is a general push to break large module functors up into individually-defined functions and values that are parameterized on a module?

---

<div class="post-metadata">

### Author: ![TyOverby](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/tyoverby/32/2213_2.png) [@TyOverby](https://discuss.ocaml.org/u/TyOverby)
#### Post date: [April 12, 2023, 2:57pm UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932/4 "2023-04-12T14:57:09Z")

</div>

I’d say that there’s a push to functors as little as possible.

It’s better to have code that uses things like Set.add instead of String.Set.add, because when you eventually want to change your code from using “string” to e.g. “Username.t”, you don’t need to chase through all the functions and swap out “String.Set._” to “Hostname.Set._”

One issue with functors is that they tend to be infectious: if some functionality is only available through a functorized API, then callers need to be functorized as well, and their callers, and so on

---

<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: [April 12, 2023, 3:33pm UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932/5 "2023-04-12T15:33:04Z")

</div>

I assume another advantage of first-class modules is that they will work better with the intended future state of modular implicits. Would just need to delete the explicit FCM argument and let it be inferred.

---

<div class="post-metadata">

### Author: ![bufordrat](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/bufordrat/32/4028_2.png) [@bufordrat](https://discuss.ocaml.org/u/bufordrat)
#### Post date: [April 12, 2023, 8:03pm UTC](https://discuss.ocaml.org/t/base-design-of-empty-in-map-set-hashtbl/11932/6 "2023-04-12T20:03:58Z")

</div>

(a bit off-topic, but I loved your Signals & Threads episode on UI stuff)
