ocaml / ocaml/ocaml

Make Map length run in O(1) instead of O(n)

Open
#12,866 22 comments 6 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature-wish stdlib
Dominant language
OCaml
Stars
6.6k
Forks
1.4k
Avg merge
3d 21h
Merged PRs (30d)
31

Description

Hi OCaml developers team 👋🏻

I want to propose a change to the OCaml standard library.

Please, let me know if it should be done differently!

What?

Currently, the implementation of Map.cardinal (a function to return the size of the Map) takes linear time:

https://github.com/ocaml/ocaml/blob/b72d99b3dbf3a593f9ff38acc4a375a2e2fd8749/stdlib/map.ml#L493-L495

I propose to

  • Change the implementation to run in constant time, independent of the tree size
  • Document that the implementation runs in constant time

Why?

It's a common expectation for a dictionary-like data structure to return its own size in a constant time.

How?

The current linear-time behaviour is a consequence of the fact that a tree node (internal Map representation) stores height instead of size.

https://github.com/ocaml/ocaml/blob/b72d99b3dbf3a593f9ff38acc4a375a2e2fd8749/stdlib/map.ml#L77-L79

I propose to change the internals and store size (and change all the relevant functions). I expect the existing test suite to be exhaustive enough to make sure that there're no regressions after this change. But, obviously, new tests are always welcome!

There's a prior art on how to rebalance a binary search tree when a node stores the size. One can refer to the Haskell implementation:

Impact

This should be a backward-compatible change, impacting only internals.


Let me know what you think!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with stdlib/map.ml, especially the internal tree-node representation and the Map.cardinal implementation linked in the issue. Trace the balancing and update functions that depend on the stored height, then review the existing Map tests. Done means Map.cardinal is constant-time, the relevant internals remain correct, and the complexity is documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
ocaml
Domain
compilers
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.