This is an alternative site for discovering Elm packages. You may be looking for the official Elm package site instead.
1.0.0 1.1.0
We were not able to find the expected elm-package.json file at this tag.
Tag 1.2.0
Committed At 2019-03-18 17:10:35 UTC

Modules

    README

    Sequence

    This is a operation-based conflict-free replicated data type (CRDT) for sequential data written in Elm. Another name for it is "ElmSEQ".

    Its implementation is derived from Nedelec et al. "LSEQ: an adaptive structure for sequences in distributed collaborative editing" (2013).

    CRDTs

    Imagine Alice and Bob editing the same text document at the same time from different devices -- but both being offline. How could their changes be merged eventually so that both ends yield the same result and the intention of both probably conflicting editions is preserved?

    Conflict-free replicated data types (CRDTs) to the rescue! In a mobile world with unreliable network connectivity, CRDTs allow for distributed offline-first applications integrating concurrent changes in a lightweight way. Data replicas are guaranteed to be eventually consistent among peers while keeping the context and order of merged operations.

    Resources

    Installation

    This library is for Elm programs. So I assume you have Elm installed. Then install this lib in your project through:

    elm install brightdb/sequence
    

    Example

    This example demonstrates an example use case of this library. First, we create concurrent operations by hand. Then we apply them to the data structure. In a real distributed environment operations would be created by peers and propagated to each other.

    Here we are dealing with text as a sequence of characters. However, the CRDT can be applied to sequences (ordered lists) of any other type (eg. todos).

    module Main exposing (main)
    
    import Sequence exposing (..)
    import String
    import Tuple
    import Html exposing (div, li, text)
    
    
    main =
        let
            -- Allocate paths (= positions) in the sequence
            -- given a preceding and a following path.
            -- In the beginning we use the minimum and maximum possible path.
            path1 =
                alloc minPath maxPath
    
            path2 =
                alloc path1 maxPath
    
            path3 =
                alloc path2 maxPath
    
            -- This path is concurrent to path2 because it's allocated between the 
            -- same pair of preceding and following paths.
            concurrentPath =
                alloc path1 maxPath
    
            -- insert operations
            ops =
                [ createInsert "me" path1 'x'
                , createInsert "me" path2 'y'
                , createInsert "me" path3 'z'
                -- a concurrent insert operation (would come in from outside)
                , createInsert "you" concurrentPath 'a'
                ]
    
            getChar value =
                case value of
                    Value a ->
                        String.fromChar a
                            |> Just
    
                    Tomb x ->
                        Nothing
    
            fold path entry lis =
                let
                    item =
                        case entry of
                            Single origin (Value char) ->
                                String.fromChar char
                                    |> text
                                    |> (\x -> [ x ])
                                    |> li []
    
                            -- concurrent values are concatenating
                            -- with commas
                            Concurrent mvr ->
                                mvrToList mvr
                                    |> List.filterMap (Tuple.second >> getChar)
                                    |> List.intersperse ","
                                    |> String.concat
                                    |> text
                                    |> (\x -> [ x ])
                                    |> li []
    
                            _ ->
                                text ""
                in
                    item :: lis
        in
            apply ops empty
                |> Tuple.first
                |> foldr fold []
                |> div []
    

    Yields:

    • x
    • y,a
    • z

    So x, y and z have been inserted by "me" while a has been inserted by "you" concurrently to y.

    Really distributed example

    For a distributed collaborative editor as a more elaborated example see brightdb-text.