Is there a name for this algebraic structure?

Hello I am wondering if there's a well known algebraic structure which follows the following patterns. Let's call it S: It's update-able with some opaque "a" (which can be an element or an operation with an element): update :: S -> a -> S There's a well defined zero for it: empty :: S Operations on it are idempotent: update s a == update (update s a) a Every S can be reconstructed from a sequence of updates: forall s. exists [a]. s == foldl update empty [a] An example of this would be Data.Set: empty = Set.empty update = flip Set.insert Is there something like this in algebra? Cheers, Gleb

Hi Gleb,
I think join/meet-semilattices captures idempotence (in a sense, convexity
and monotonicity) pretty well, but they may require a slightly
different/stronger structure than what you may need. Depending on the
properties you really need, maybe a Poset is enough.
For example, the "meet" function maps pairs of elements of "S" to elements
of "S". Whereas your "update" takes an "S" and an arbitrary "a", which is
slightly different. However, if you have an existing "update" function for
some given a, one possibility is to project any "a" to an "S" with "update
empty :: a -> S". Then you can work using the semilattice.
Cheers,
--Lucas
2015-04-20 22:12 GMT+01:00 Gleb Peregud
Hello
I am wondering if there's a well known algebraic structure which follows the following patterns. Let's call it S:
It's update-able with some opaque "a" (which can be an element or an operation with an element):
update :: S -> a -> S
There's a well defined zero for it:
empty :: S
Operations on it are idempotent:
update s a == update (update s a) a
Every S can be reconstructed from a sequence of updates:
forall s. exists [a]. s == foldl update empty [a]
An example of this would be Data.Set:
empty = Set.empty update = flip Set.insert
Is there something like this in algebra?
Cheers, Gleb
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

You said in words that
Every S can be reconstructed from a sequence of updates:
but your formula
forall s. exists [a]. s == foldl update empty [a]
says that a (not necessarily unique) sequence of updates can be reconstructed from every S. I think you meant something like "there are no elements of S but those that can be constructed by a sequence of updates". I'm a little confused by "a" being lower case. There's a little wrinkle that tells me this isn't going to be simple. type A = Bool newtype S = S [A] empty :: S empty = S [] update :: S -> A -> S update o@(S (x:xs)) y | x == y = o update (S xs) y = S (y:xs) reconstruct :: S -> [A] reconstruct (S xs) = xs Here update is *locally* idempotent: update (update s a) a == update s a But it's not *globally* idempotent: you can build up a list of any desired length, such as S [False,True,False,True,False], as long as the elements alternate. Perhaps I have misunderstood your specification.

Thanks for answers and sorry for goofy definitions and laws. I didn't think
it thoroughly enough.
In general I think I was looking for something slightly less powerful than
this CRDTs:
https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type
Basically I would like to find an algebraic structure which corresponds to
a versioned shared data-structure which can be synchronized using log
replication between multiple actors/applications/devices. Think if a
structure which can be used to synchronize chat room with messages or
friends list or notification panel content, etc. It should work over
intermittent connection, with a single source of truth (a server), can be
incrementally updated to the latest version based on some cached stale
version, etc. I think I need to think a bit more about this to find a
proper definitions and laws.
Cheers,
Gleb
On Tue, Apr 21, 2015 at 4:51 AM, Richard A. O'Keefe
You said in words that
Every S can be reconstructed from a sequence of updates:
but your formula
forall s. exists [a]. s == foldl update empty [a]
says that a (not necessarily unique) sequence of updates can be reconstructed from every S. I think you meant something like "there are no elements of S but those that can be constructed by a sequence of updates".
I'm a little confused by "a" being lower case.
There's a little wrinkle that tells me this isn't going to be simple.
type A = Bool newtype S = S [A]
empty :: S
empty = S []
update :: S -> A -> S
update o@(S (x:xs)) y | x == y = o update (S xs) y = S (y:xs)
reconstruct :: S -> [A]
reconstruct (S xs) = xs
Here update is *locally* idempotent: update (update s a) a == update s a But it's not *globally* idempotent: you can build up a list of any desired length, such as S [False,True,False,True,False], as long as the elements alternate.
Perhaps I have misunderstood your specification.

A CRDT may be a commutative semi-group, where the operation is merge. Given two conflicting versions, the merge operation yields an updated version. Associativity is important for this use case since one does not know the order that versions will be reconciled. Commutativity is important for this use case since version A merged with version B should be the same as version B merged with version A. Hopefully this helps. Gleb Peregud writes:
Thanks for answers and sorry for goofy definitions and laws. I didn't think it thoroughly enough.
In general I think I was looking for something slightly less powerful than this CRDTs: https://en.wikipedia.org/wiki/Conflict-free_replicated_data_type
Basically I would like to find an algebraic structure which corresponds to a versioned shared data-structure which can be synchronized using log replication between multiple actors/applications/devices. Think if a structure which can be used to synchronize chat room with messages or friends list or notification panel content, etc. It should work over intermittent connection, with a single source of truth (a server), can be incrementally updated to the latest version based on some cached stale version, etc. I think I need to think a bit more about this to find a proper definitions and laws.
Cheers, Gleb
On Tue, Apr 21, 2015 at 4:51 AM, Richard A. O'Keefe
wrote: You said in words that
Every S can be reconstructed from a sequence of updates:
but your formula
forall s. exists [a]. s == foldl update empty [a]
says that a (not necessarily unique) sequence of updates can be reconstructed from every S. I think you meant something like "there are no elements of S but those that can be constructed by a sequence of updates".
I'm a little confused by "a" being lower case.
There's a little wrinkle that tells me this isn't going to be simple.
type A = Bool newtype S = S [A]
empty :: S
empty = S []
update :: S -> A -> S
update o@(S (x:xs)) y | x == y = o update (S xs) y = S (y:xs)
reconstruct :: S -> [A]
reconstruct (S xs) = xs
Here update is *locally* idempotent: update (update s a) a == update s a But it's not *globally* idempotent: you can build up a list of any desired length, such as S [False,True,False,True,False], as long as the elements alternate.
Perhaps I have misunderstood your specification.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
-- Kyle Marek-Spartz

On Tue, Apr 21, 2015 at 02:51:16PM +1200, Richard A. O'Keefe wrote:
You said in words that
Every S can be reconstructed from a sequence of updates:
but your formula
forall s. exists [a]. s == foldl update empty [a]
says that a (not necessarily unique) sequence of updates can be reconstructed from every S. I think you meant something like "there are no elements of S but those that can be constructed by a sequence of updates".
Those sound like the same thing to me!

Gleb Peregud wrote:
I am wondering if there's a well known algebraic structure which follows the following patterns. Let's call it S:
It's update-able with some opaque "a" (which can be an element or an operation with an element):
update :: S -> a -> S
There's a well defined zero for it:
empty :: S
Operations on it are idempotent:
update s a == update (update s a) a
Every S can be reconstructed from a sequence of updates:
forall s. exists [a]. s == foldl update empty [a]
If you reverse the arguments of the `update` function, then you get a map update :: A -> (S -> S) from the type `A` of "updates" to the monoid of maps Endo S . Another way to look at it is to consider a monoid `M[A]` which is generated by elements of the type `A`, subject to the condition that these elements are idempotent. In other words, you consider the following quotient M[A] = words in A / x^2 = x for each x\in A Then, the update function is a morphism of monoids: update :: M[A] -> S Mathematicians like to conflate the type `S` and the map `update` a little bit and speak of this as *representation* of your monoid. This is a useful way to look at things, for instance when it comes to the representation of groups. In any case, this is how I would approach the problem of turning this into an algebraic structure, there are probably many other ways to do that as well. Best regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com
participants (7)
-
Albert Y. C. Lai
-
Gleb Peregud
-
Heinrich Apfelmus
-
Kyle Marek-Spartz
-
lucas di cioccio
-
Richard A. O'Keefe
-
Tom Ellis