# "Extending" modules from the Stdlib?

**URL:** <https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969>\
**Category:** Learning\
**Created:** [June 3, 2022, 9:32pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969 "2022-06-03T21:32:59Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![user1](https://avatars.discourse-cdn.com/v4/letter/u/5daacb/32.png) [@user1](https://discuss.ocaml.org/u/user1)\
**Post date:** [June 3, 2022, 9:32pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/1 "2022-06-03T21:32:59Z")

</div>

I find myself missing some functions from some modules in the Stdlib. Is it fine to simply overwrite them by writing new files, say, `stack.mli` and `stack.ml` in my `/lib` directory (in a project generated using `dune init proj project_name`) and then calling, say, `Stack.mem`, etc ? Or are there downsides and preferred solutions, maybe using different names for the extended modules, or functors ?

```auto
(* stack.mli *)
include module type of Stack

val mem : 'a -> 'a Stack.t -> bool
(** Check if the argument is a member of the stack. *)

val create_sng : 'a -> 'a Stack.t
(** Return a stack with the argument as single element. *)

val junk : 'a Stack.t -> unit
(** Remove the top element of a stack, throwing an exception in the case of
    an empty stack. *)

```

```auto
(* stack.ml *)
include Stack

let mem x t =
  let f b y = b || y = x in
  Stack.fold f false t

let create_sng x =
  let res = create () in
  Stack.push x res;
  res

let junk t = ignore (Stack.pop t)

```

Thanks.

---

<div class="post-metadata">

**Author:** ![OCamlUser](https://avatars.discourse-cdn.com/v4/letter/o/3ec8ea/32.png) [@OCamlUser](https://discuss.ocaml.org/u/OCamlUser)\
**Post date:** [June 4, 2022, 12:22am UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/2 "2022-06-04T00:22:49Z")

</div>

Edit: here’s a similar previous discussion [Extend existing module](https://discuss.ocaml.org/t/extend-existing-module/1389)

Along with another: [Modules that extend modules from third-party packages](https://discuss.ocaml.org/t/modules-that-extend-modules-from-third-party-packages/3777)

Not exactly the same, but provides a lot of context.

---

<div class="post-metadata">

**Author:** ![user1](https://avatars.discourse-cdn.com/v4/letter/u/5daacb/32.png) [@user1](https://discuss.ocaml.org/u/user1)\
**Post date:** [June 4, 2022, 4:09pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/3 "2022-06-04T16:09:19Z")

</div>

Thanks. I see that my method is discouraged, but it is not said in favor of which other method. It looks like I should rename my files `stack1.mli` / `stack1.ml` and should not use `include`. Then, in my main file, I should call either `Stack.xxx` for the functions of the Stdlib or `Stack1.yyy` for my new functions.

Since I also want to add functions for lists, maybe it’s better to have files `util.mli` / `util.ml` where I put my stack functions and my list functions together, and then refer to them as `Util.xxx` in my main file ?

---

<div class="post-metadata">

**Author:** ![Levi\_Roth](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/levi_roth/32/2268_2.png) [@Levi\_Roth](https://discuss.ocaml.org/u/Levi_Roth)\
**Post date:** [June 4, 2022, 5:07pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/4 "2022-06-04T17:07:53Z")

</div>

> [@user1](#):
>
> I see that my method is discouraged

I didn’t get the sense of a consensus that it’s discouraged from those threads. In your shoes I’d probably use the `module type of struct include Stack end` form.

---

<div class="post-metadata">

**Author:** ![Mhouh](https://avatars.discourse-cdn.com/v4/letter/m/838e76/32.png) [@Mhouh](https://discuss.ocaml.org/u/Mhouh)\
**Post date:** [June 18, 2022, 2:08pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/5 "2022-06-18T14:08:09Z")

</div>

When I use a modified version of a Stdlib module, I alter it locally:

```ocaml
module Stdlib_submodule = struct
  include Stdlib_submodule
  let extension ... = ...
end

```

Never really had the need for it though…

---

<div class="post-metadata">

**Author:** ![Leonidas](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/leonidas/32/4039_2.png) [@Leonidas](https://discuss.ocaml.org/u/Leonidas)\
**Post date:** [June 21, 2022, 2:02pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/6 "2022-06-21T14:02:08Z")

</div>

Another pragmatic option would be instead of writing an somewhat incomplete extended standard library, use one of the existing ones like Base or Containers, which come with a number of frequently reimplemented functions from the get-go.

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [June 21, 2022, 2:26pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/7 "2022-06-21T14:26:19Z")

</div>

Depends on your kind of pragmatism. If you just need a function here and there, simply adding them to your project is very pragmatic from a maintenance perpsective.

---

<div class="post-metadata">

**Author:** ![user1](https://avatars.discourse-cdn.com/v4/letter/u/5daacb/32.png) [@user1](https://discuss.ocaml.org/u/user1)\
**Post date:** [June 21, 2022, 7:52pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/8 "2022-06-21T19:52:11Z")

</div>

I don’t know Containers, I’m going to look at it, thanks ! As for Base, it actually overwrites some functions of the Stdlib (even some very common ones) and gives them a different meaning, which is a big NO.

By the way: I think it should be a big NO for everyone. What happens when a third person will want to rewrite a third “standard library” ? And a fourth ? We’ll end up with various OCaml-looking languages and maintenance (and learning) will be harder for everyone. It will be like the XKCD “standards” thing. Why couldn’t they join forces instead of competing ? Or if they want to enrich the library with other features, fine, but not rewriting the existing ones with a different meaning. And if they think of better design choices, they could push them to Stdlib, and everyone would benefit from it. Collaboration, not competition !

---

<div class="post-metadata">

**Author:** ![dbuenzli](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/dbuenzli/32/18_2.png) [@dbuenzli](https://discuss.ocaml.org/u/dbuenzli)\
**Post date:** [June 21, 2022, 8:03pm UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/9 "2022-06-21T20:03:37Z")

</div>

> [@user1](#):
>
> Why couldn’t they join forces instead of competing ?

Because different entities have different constraints, goals, ideas and need for control. There’s no problem with that.

Just use what you think is good for yourself and avoid the rest.

---

<div class="post-metadata">

**Author:** ![Leonidas](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/leonidas/32/4039_2.png) [@Leonidas](https://discuss.ocaml.org/u/Leonidas)\
**Post date:** [June 22, 2022, 7:51am UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/10 "2022-06-22T07:51:09Z")

</div>

> [@user1](#):
>
> As for Base, it actually overwrites some functions of the Stdlib (even some very common ones) and gives them a different meaning, which is a big NO.

I think this is actually a big advantage because it makes the Stdlib look like it was designed in 2015, that means it incorporates a lot of learnings that we got from the original standard library. For good reasons the OCaml stdlib can’t really change but I do enjoy that I can just point people to use `(Base.)List.find` instead of always knowing not to use `Stdlib.List.find` but use the slightly more obscure `Stdlib.List.find_opt`, etc, etc.

In fact we already have a lot of “standard libraries” because often every project comes with its own implementation of things that were not in the standard library or weren’t there when the project was written or are not in the standard library of the minimum version of OCaml that they support, so for every project one has to look up how to achieve pretty simple things like “What do `Map`s support here, how can I get a `Set`, where are the prettyprinters, how do I deal with result, is there `let*` syntax” etc and the situation is pretty much what you describe.

It doesn’t help that some of the standard extensions have pretty bad APIs, e.g. a `Map.update` that can’t delete keys because the function does not accept `'a option` as a return value, so you end up having to build your own version of `Map.update` on top of it.

---

<div class="post-metadata">

**Author:** ![user1](https://avatars.discourse-cdn.com/v4/letter/u/5daacb/32.png) [@user1](https://discuss.ocaml.org/u/user1)\
**Post date:** [June 22, 2022, 9:10am UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/11 "2022-06-22T09:10:07Z")

</div>

Thanks @Leonidas for the explanations. Obviously I cannot tell which one is better, but I was simply frustrated to see two different and incompatible “standard” libraries.  
As @dbuenzli advises, I will continue with Stdlib, which seems sufficient for now (and hope that I won’t discover, when my program is twice larger, that I have to switch to Base).

---

<div class="post-metadata">

**Author:** ![shonfeder](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/shonfeder/32/424_2.png) [@shonfeder](https://discuss.ocaml.org/u/shonfeder)\
**Post date:** [June 22, 2022, 11:39am UTC](https://discuss.ocaml.org/t/extending-modules-from-the-stdlib/9969/12 "2022-06-22T11:39:33Z")

</div>

Fwiw, containers is a very good overlay if you want something that plays nice with the Stdlib.
