I'm looking for a class in like the following in a Haskell library (or at least to know the mathematical name for such a thing):
class Monoid patch => MyThing patch t where
applyPatch :: t -> patch -> t
I can have instances like this:
instance MyThing (Last t) t where
applyPatch x patch = case getLast patch of
Just y => y
Nothing => x
But I could also have instances like this:
instance MyThing (Dual (Map key value)) (Map key value) where
applyPatch x patch = ...
Where the patch essentially adds and/or replaces key/value pairs from the map.
One could go further if you wanted to do deletions:
instance MyThing (Dual (Map key (Maybe value))) (Map key value) where
applyPatch x patch = ...
Aside from patch
being a monoid, the main law I want this class to follow is associativity, concretely:
forall (x :: t, y :: patch, z :: patch).
(x `applyPatch` y) `applyPatch` z == x `applyPatch` (y <> z)
My thought (well, actually ChatGPTs thought) that this was an "Affine Space", but the issue is that my underlying "patch" type, whilst a monoid, is not an additive group, because it doesn't have inverses.
So basically I think I want an affine space without inverses. Does this exist, either mathematically or in a Haskell library?
What you have described amounts to a monoid (or semigroup) action. One place where a class for that can be found is Data.Monoid.Action
from monoid-extras:
class Action m s where
act :: m -> s -> s
Paraphrasing the documentation, the laws are:
act (m1 <> m2) = act m1 . act m2
-- Also, if m is a monoid:
act mempty = id
-- Additionally, if s has some algebraic structure then act m preserves it.
-- For instance, if s is a monoid, then act m should be a monoid homomorphism.