You're reading the public-facing archive of the Category Theory Zulip server.
To join the server you need an invite. Anybody can get an invite by contacting Matteo Capucci at name dot surname at gmail dot com.
For all things related to this archive refer to the same person.
I want to talk about some monoids for ordering, in the context of Haskell/PureScript programming, just because I find it interesting :)
Haskell has a total ordering class called Ord
which captures types that have a total order on them. This is useful for putting things into Sets or indexing them in Maps. Sorting, nubbing, etc.
I'll copy the PS example, bc it's easier, but Haskell is the same:
class Eq a <= Ord a where compare :: a -> a -> Ordering
Where (Ordering
)[https://pursuit.purescript.org/packages/purescript-prelude/4.1.1/docs/Data.Ordering#t:Ordering] is a three-element monoid:
data Ordering = LT | GT | EQ instance semigroupOrdering :: Semigroup Ordering where append LT _ = LT append GT _ = GT append EQ y = y instance monoidOrdering :: Monoid Ordering where mempty = EQ invert :: Ordering -> Ordering invert GT = LT invert EQ = EQ invert LT = GT
It has two left-absorbing elements and the identity. It turns out that it captures lexical orders on products very well: if we have a product (a, b)
then we have compare (a, b) (c, d) = compare a c <> compare b d
(where we write <>
for the semigroup operation).
It also has one non-trivial involution which can be used to state one of the laws: compare a b = invert (compare b a)
(actually, I'm not sure what law that actually is … antisymmetry?)
It also has a nice homomorphism areEq
to the Boolean monoid under conjunction, which we call Conj Boolean
in PS, that sends the non-empty elements to false
. This can be used to state the expected behavior WRT to the parent class Eq
: areEq (compare a b) == (a == b)
.
Total orderings are nice for sorting and other computational things, but partial orderings are more common for capturing the semantics of some datatypes. Can we also describe them with a monoid?
I think for products, you might have a lattice.
The answer is yes, of course! I just had to make it myself:
data POrdering = PLT | PEQ | PGT | UNC instance semigroupPOrdering :: Semigroup POrdering where append UNC _ = UNC append _ UNC = UNC append PEQ a = a append a PEQ = a append PLT PLT = PLT append PLT PGT = UNC append PGT PLT = UNC append PGT PGT = PGT instance monoidPOrdering :: Monoid POrdering where mempty = PEQ inverse :: POrdering -> POrdering inverse PLT = PGT inverse PGT = PLT inverse PEQ = PEQ inverse UNC = UNC
This time we have three idempotent elements and the identity: one absorbing element, and two that annihilate each other (i.e. PGT <> PLT == UNC == PLT <> PGT
).
We still have the nice homomorphism and involution as mentioned above. But notice that it's commutative now!
Now our interpretation for products is that pcompare (a, b) (c, d) = pcompare a c <> pcompare b d
and the more familiar semantics is that (a, b) <= (c, d) when a <= b and c <= d
Yeah, that lattice.
PEQ is the bottom, UNC is the top, and you take joins.
Or flip it upside down.
Seems suggestive that you're classifying two values of a partial order by mapping them to a lattice (which is also a partial order).
I hadn't actually thought about it that way, but yes! One of the simplest lattices
We can generate an ordering function from a partial order >=
operator:
fromGERelation :: forall t. (t -> t -> Boolean) -> (t -> t -> POrdering) fromGERelation f a b = case f a b, f b a of true, true -> PEQ true, false -> PGT false, true -> PLT false, false -> UNC
Or, I guess the process I meant is more complicated. Classifying a compound partial order by mapping to a 'simpler' partial order and combining there.
You can factor products out. Is that a good phrasing? I'm not quite sure ...
One reason why we use (p)compare
to define an order, instead of the mathematical convention of <=
, is computational efficiency: we might as well give all the information we have at once, instead of computing both <=
and >=
, which would be wasteful.
Is there a name for the standard product partial order? I guess it would be the categorical product … but I find it interesting how different the lexical order and the partial product order are. They essentially never agree, even though they are both the natural choices for ordering products in closely related ways (only one extra law for total orders).
It's the categorical product, which is also the product of the partial orders considered to be categories, I believe. I'm not sure if there's a nice characterization of the lexicographic order.
The lexicographic order probably cannot be specified using a universal property, because it is not invariant under isomorphism … (a, b) <= (c, d)
isn't the same as (b, a) <= (d, c)
. Does that seem right? I'm too tired rn to actually check the categorical details lol
Well, it can't be a construction that's commutative.
nlab doesn't have anything particularly nice categorically to say about it.
One more note before I go to bed: my particular application of partial orders in the above project was resolving ambiguity during parsing. For each parsing rule I knew was ambiguous, I would look at the AST and assign disambiguation precedences, and then I would look for a parse that was maximally preferred over all others. If, at the end of this discarding, there was still not a unique parse, then I would fail parsing, but so far I haven't seen an instance of that happen: The assumption is that parse ambiguity is roughly compositional, so if there are two ambiguous rules that can both individually trigger on the same string, there should be a case where both of their preferred parsings were found.
BTW, the three-element monoid LT | GT | EQ
is known in the literature as the "flip-flop monoid" cf. https://en.wikipedia.org/wiki/Semigroup_with_three_elements