Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Data.Ordered

Explicit ordering witnesses: the branded, statically coherent path to ordered maps.

An unbranded Map(k, v) is ordered by the ambient canonical Ord(k). When a program needs two orderings of the same keys at once (one map ascending, one descending), the phantom brand on Map(k, v, brand) keeps their values from being mixed. with_ordering hands its body a witness carrying a comparator; the witness’s brand is a rigid, scope-local skolem, so a map built under one witness never unifies with a map built under another. Passing a map of one witness to another witness’s operation is a compile error that names both brands.

This is the explicit half of the ordered-container coherence story, closed statically. The implicit using ordRev path (calling the ambient map_insert under a non-canonical Ord) is guarded at runtime when an ordered map crosses a package boundary: Wire’s map reader faults when a map arrives ordered by a different Ord(k) than the reader canonicalizes. No claim is made here of automatic static closure of the implicit path.

Opt-in: this module is not in Base, so ambient effect rows and the unbranded Map surface are untouched unless a program imports it.

Types

OrdWitness

newtype OrdWitness(k, brand) = OrdBy((k, k) -> Int)

An ordering witness: a comparator branded by the phantom brand. The only way to obtain one is with_ordering, which mints a fresh brand per call, so two witnesses always carry incompatible brands.

OrderedMap

newtype OrderedMap(k, v, brand) = OrderedMap(Map(k, v, brand))

A map whose representation is sealed to the comparator carried by its witness. Hiding this wrapper matters as much as hiding OrdWitness: a raw Map(k, v, brand) can otherwise be instantiated at any phantom brand and smuggled into the explicit-ordering API after being built by another comparator.

Functions and Values

with_ordering

with_ordering : forall a b. ((a, a) -> Int, forall brand. (Data.Ordered.OrdWitness(a, brand)) -> b) -> b

Run body with a fresh ordering witness carrying cmp. The witness’s brand is rigid and unique to this call: a map built under it cannot be handed to a different witness’s operation, and that mismatch is a compile error naming both brands. The result a may not mention the brand, so a branded map never escapes the block, only a summary of it (a size, a looked-up value, an encoded form).

The brand binder is spelled brand rather than a bare letter on purpose: it must not collide with the a, b, c a scheme’s own quantifiers are canonicalized to, which would capture the result type under the inner quantifier.

with_ordering(\(a, b) -> cmp(a, b), \(w) ->
  ord_lookup(w, 1, ord_insert(w, 1, "a", ord_empty(w))))
Some(a)

Named as the scoping form it is, since it reads at the call site as the block that opens the brand rather than as another operation on an ordered map.

ord_empty

ord_empty : forall a b c. (Data.Ordered.OrdWitness(a, b)) -> Data.Ordered.OrderedMap(a, c, b)

The empty map under witness w, carrying w’s brand.

ord_insert

ord_insert : forall a b c. (Data.Ordered.OrdWitness(a, b), a, c, Data.Ordered.OrderedMap(a, c, b)) -> Data.Ordered.OrderedMap(a, c, b)

Insert under witness w; the result carries w’s brand.

with_ordering(\(a, b) -> cmp(a, b), \(w) ->
  ord_size(w, ord_insert(w, 1, "a", ord_empty(w))))
1

ord_lookup

ord_lookup : forall a b c. (Data.Ordered.OrdWitness(a, b), a, Data.Ordered.OrderedMap(a, c, b)) -> Option(c)

Look key up under witness w. Only a map of w’s brand type-checks here.

with_ordering(\(a, b) -> cmp(a, b), \(w) ->
  ord_lookup(w, 9, ord_insert(w, 1, "a", ord_empty(w))))
None

ord_member

ord_member : forall a b c. (Data.Ordered.OrdWitness(a, b), a, Data.Ordered.OrderedMap(a, c, b)) -> Bool

True when key is present under witness w.

with_ordering(\(a, b) -> cmp(a, b), \(w) ->
  ord_member(w, 1, ord_insert(w, 1, "a", ord_empty(w))))
true

ord_to_list

ord_to_list : forall a b c. (Data.Ordered.OrdWitness(a, b), Data.Ordered.OrderedMap(a, c, b)) -> List((a, c))

The (key, value) pairs of a w-branded map, in tree (in-order) order.

with_ordering(\(a, b) -> cmp(a, b), \(w) ->
  ord_to_list(w, ord_insert(w, 2, "b", ord_insert(w, 1, "a", ord_empty(w)))))
[(1, a), (2, b)]

ord_size

ord_size : forall a b c. (Data.Ordered.OrdWitness(a, b), Data.Ordered.OrderedMap(a, c, b)) -> Int

The number of entries in a w-branded map.

with_ordering(\(a, b) -> cmp(a, b), \(w) ->
  ord_size(w, ord_insert(w, 2, "b", ord_insert(w, 1, "a", ord_empty(w)))))
2