This is a prototype of a CRDT for sequential data written in Elm.
Work in progress! Use with caution.
Implementation stems from Nedelec et al. "LSEQ: an adaptive structure for sequences in distributed collaborative editing" (2013).
The unique identifier of a Entry's position in the sequence. It's called "path" because the data type consists of multiple layers comparable to a filesystem's directories. A path to a value works like a path to a file.
The complete self-contained op(eration). origin is the identifier for the
creating user/instance. If the Entry at path already contains a MVR apply the
operation at
target's value.
An entry in the sequence might be a single value (just one user applied an operation on it) or a multi-value registry (MVR) in case multiple users a applied operation at this path.
The actual value. After applying an Insert operation it is Value a, after
a Remove operation it is a Tomb (TombValue a). So storage of removed values never gets
freed.
If a remove operation is applied at a path which has a value, it's turned
into Tomb (TombValue a). If the operation is applied on a free path it
becomes TombUnknown. If an insert operation is applied after this, it's
turned into TombValue a finally. This way it does not matter in which order
insert and remove operation are applied.
All data manipulation happens through Operations. It either is an Insert a or Remove.
A multi-value registry is a dictionary of user identifiers and Values.
Get its contents with mvrToList.
Allocate a path given it's lower and upper bounds (non-inclusive). The bounds should be paths that are already taken and the possible path's between should all be free.
Create an insert operation. Pass it the user identifier, a path and the value to insert.
Create a remove operation. Pass it the removing user's identifier, the user identifier of the removed value (ie. to target it in a MVR) and the path.
Apply multiple ops at once to a sequence. Returns the updated sequence and list of successful operations (which actually changed something).
An empty sequence.
Lookup an entry at the given path.
Return the first entry of the sequence and its path.
If the sequence is empty returns Nothing.
Return the last entry of the sequence and its path.
If the sequence is empty returns Nothing.
Return the entry and its path after the given path in the sequence.
Returns Nothing if there none.
Return the entry and its path before the given path in the sequence.
Returns Nothing if there none.
Fold a sequence from the left.
Fold a sequence from the right.
Inspect an MVR by turning it into a list of tuples of the user identifier and the Value.
Decode an Op.
Encoder an Op given an value specific encoder.
The lowest path possible
The greatest path possible
The data type itself. Takes a user-defined type as its value type.