Open treeowl opened 1 month ago
I know I suggested this in https://github.com/haskell/containers/pull/1025#issuecomment-2286914198, but it needs more thought 😄
What would be the distinction between Map.Internal
and Map.Unsafe
in this case?
I think of Unsafe
as having much stronger stability expectations than Internal
.
That sounds fine in theory, but in practice I haven't seen Internal
modules being unstable at all (at least since I have been paying attention to it).
I'm just trying to see if we can avoid having too many modules.
Alternative option 1: We make Internal
stable (and it follows PVP) and move unsafe functions there.
Alternative option 2 (more drastic): We add Unsafe
but hide Internal
. Unsafe
is stable. The exports in the public module and the exports in the Unsafe
module are disjoint and together make up the Internal
module.
To get a sense of things,
List of functions in Data.Map.Lazy
that can violate Map
invariants:
fromAscList
fromAscListWith
fromAscListWithKey
fromDistinctAscList
fromDescList
fromDescListWith
fromDescListWithKey
fromDistinctDescList
mergeWithKey
mapKeysMonotonic
More functions in Data.Map.Internal
that can violate Map
invariants:
Map
constructorsWhenMissing
constructorsWhenMatched
constructorsbin
balance
balanceL
balanceR
insertMax
link
link2
glue
That sounds fine in theory, but in practice I haven't seen
Internal
modules being unstable at all (at least since I have been paying attention to it).
You write this just a couple months after changing the internal representations of IntSet
and IntMap
!
That's true but it is a rare event 😄
IntMap
hasn't changed in ~19 years. IntSet
has changed once ~13 years ago (packed tips added).
The API currently exposes a few functions that break the abstraction barrier and sometimes allow the construction of invalid structures. We should collect those in separate modules, with the hope of eventually removing them from the "safe" interface.