Skip to content
Tech News
← Back to articles

Monuses and Heaps

read original more articles
Why This Matters

This article introduces the concept of monus, an algebraic structure that enhances heap-based algorithms by supporting partial subtraction, enabling more flexible and efficient sorting and search operations. Its development is significant for advancing algorithmic capabilities in graph search and data structure management, impacting both industry applications and consumer-facing technologies. Understanding monus can lead to more optimized algorithms and innovative data handling techniques in the tech industry.

Key Takeaways

Monuses and Heaps

Posted on March 3, 2026

This post is about a simple algebraic structure that I have found useful for algorithms that involve searching or sorting based on some ordered weight. I used it a bit in a pair of papers on graph search (2021; 2025), and more recently I used it to implement a version of the Phases type (Easterly 2019) that supported arbitrary keys, inspired by some work by Blöndal (2025a; 2025b) and Visscher (2025).

The algebraic structure in question is a monus, which is a kind of monoid that supports a partial subtraction operation (that subtraction operation, denoted by the symbol ∸, is itself often called a “monus”). However, before giving the full definition of the structure, let me first try to motivate its use. The context here is heap-based algorithms. For the purposes of this post, a heap is a tree that obeys the “heap property”; i.e. every node in the tree has some “weight” attached to it, and every parent node has a weight less than or equal to the weight of each of its children. So, for a tree like the following:

The heap property is satisfied when a ≤ b a \leq b , a ≤ c a \leq c , b ≤ d b \leq d , and b ≤ e b \leq e .

Usually, we also want our heap structure to have an operation like popMin :: Heap k v -> Maybe (v, Heap k v) that returns the least-weight value in the heap paired with the rest of the heap. If this operation is efficient, we can use the heap to efficiently implement sorting algorithms, graph search, etc. In fact, let me give the whole basic interface for a heap here:

popMin :: Heap k v -> Maybe (v, Heap k v) k v(v,k v) insert :: k -> v -> Heap k v -> Heap k v k vk v empty :: Heap k v k v

Using these functions it’s not hard to see how we can implement a sorting algorithm:

sortOn :: (a -> k) -> [a] -> [a] (ak)[a][a] = unfoldr popMin . foldr (\x -> insert (k x) x) empty sortOn kunfoldr popMin(\xinsert (k x) x) empty

The monus becomes relevant when the weight involved is some kind of monoid. This is quite a common situation: if we were using the heap for graph search (least-cost paths or something), we would expect the weight to correspond to path costs, and we would expect that we can add the costs of paths in a kind of monoidal way. Furthermore, we would probably expect the monoidal operations to relate to the order in some coherent way. A monus (Amer 1984) is an ordered monoid where the order itself can be defined in terms of the monoidal operations :

... continue reading