-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Something along the lines of:
class (Ord m, LeftGCDMonoid m, MonoidNull m) => Lexicographic m where
To rule out cases where the ordering changes over the course of the comparison, we should have the following law:
prop :: Lexicographic m => m -> m -> m -> Bool
prop x y z = compare x y == compare (z <> x) (z <> y)
It seems like we may also need a law that any value in between two other values should share a equal or longer prefix with both of them than the two do with each other, to rule out cases like bar < foo < baz, as it's unclear whether or not that follows from the above law:
prop :: Lexicographic m => m -> m -> m -> Bool
prop x y z = (x <= y && y <= z)
<= ( commonPrefix x z `isPrefixOf` commonPrefix x y
&& commonPrefix x z `isPrefixOf` commonPrefix y z
)
However it's worth analyzing these laws further to make sure they are correct.
Given the above it would be possible to build an efficient radix-tree library built on top of Map that works for any arbitrary Lexicographic key.
Using the three classes separately has a variety of downsides:
You can't use Map.lookupLE/GT to search for shared prefixes, you have to exhaustively search the entire Map when inserting/editing.
You can't expose efficient minimum/lookupLT/etc. functions that run in logarithmic/key-length time and instead they all have to traverse the entire structure.