[
    {
        "name": "Sequence",
        "comment": " This is a prototype of a CRDT for sequential data written in Elm.\n\n**Work in progress!** Use with caution.\n\nImplementation stems from Nedelec et al. \"LSEQ: an adaptive structure for sequences in distributed collaborative editing\" (2013).\n\n\n# Definition\n\n@docs Sequence, Path, Op, Entry, Value, TombValue, Operation, MVR\n\n\n# Operations\n\n@docs alloc, createInsert, createRemove, apply\n\n\n# Sequence handling\n\n@docs empty, get, first, last, after, before, foldl, foldr\n\n\n# MVR handling\n\n@docs mvrToList\n\n\n# Decoders\n\n@docs decodeOp, encodeOp\n\n\n# Paths\n\n@docs minPath, maxPath, path, comparePath\n\n",
        "unions": [
            {
                "name": "Entry",
                "comment": " An entry in the sequence might be a single value (just one user applied an\noperation on it) or a multi-value registry (MVR) in case multiple users a\napplied operation at this path.\n",
                "args": [
                    "a"
                ],
                "cases": [
                    [
                        "Single",
                        [
                            "String",
                            "Value a"
                        ]
                    ],
                    [
                        "Concurrent",
                        [
                            "MVR a"
                        ]
                    ]
                ]
            },
            {
                "name": "MVR",
                "comment": " A multi-value registry is a dictionary of user identifiers and Values.\nGet its contents with [`mvrToList`](#mvrToList).\n",
                "args": [
                    "a"
                ],
                "cases": []
            },
            {
                "name": "Operation",
                "comment": " All data manipulation happens through `Operation`s. It either is an `Insert a` or `Remove`.\n",
                "args": [
                    "a"
                ],
                "cases": [
                    [
                        "Insert",
                        [
                            "a"
                        ]
                    ],
                    [
                        "Remove",
                        []
                    ]
                ]
            },
            {
                "name": "Path",
                "comment": " The unique identifier of a Entry's position in the sequence.\nIt's called \"path\" because the data type consists of multiple layers\ncomparable to a filesystem's directories. A path to a value works like\na path to a file.\n",
                "args": [],
                "cases": []
            },
            {
                "name": "Sequence",
                "comment": " The data type itself. Takes a user-defined type as its value type.\n",
                "args": [
                    "a"
                ],
                "cases": []
            },
            {
                "name": "TombValue",
                "comment": " If a remove operation is applied at a path which has a value, it's turned\ninto `Tomb (TombValue a)`. If the operation is applied on a free path it\nbecomes `TombUnknown`. If an insert operation is applied after this, it's\nturned into `TombValue a` finally. This way it does not matter in which order\ninsert and remove operation are applied.\n",
                "args": [
                    "a"
                ],
                "cases": [
                    [
                        "TombValue",
                        [
                            "a"
                        ]
                    ],
                    [
                        "TombUnknown",
                        []
                    ]
                ]
            },
            {
                "name": "Value",
                "comment": " The actual value. After applying an Insert operation it is `Value a`, after\na Remove operation it is a `Tomb (TombValue a)`. So storage of removed values never gets\nfreed.\n",
                "args": [
                    "a"
                ],
                "cases": [
                    [
                        "Value",
                        [
                            "a"
                        ]
                    ],
                    [
                        "Tomb",
                        [
                            "TombValue a"
                        ]
                    ]
                ]
            }
        ],
        "aliases": [
            {
                "name": "Op",
                "comment": " The complete self-contained op(eration). `origin` is the identifier for the\ncreating user/instance. If the Entry at `path` already contains a MVR apply the\noperation at\n`target`'s value.\n",
                "args": [
                    "b"
                ],
                "type": "{ origin : String, target : String, path : Path, op : Operation b }"
            }
        ],
        "values": [
            {
                "name": "after",
                "comment": " Return the entry and its path after the given path in the sequence.\nReturns `Nothing` if there none.\n",
                "type": "Path -> Sequence a -> Maybe ( Path, Entry a )"
            },
            {
                "name": "alloc",
                "comment": " Allocate a path given it's lower and upper bounds (non-inclusive).\nThe bounds should be paths that are already taken and the possible path's\nbetween should all be free.\n",
                "type": "Path -> Path -> Path"
            },
            {
                "name": "apply",
                "comment": " Apply multiple ops at once to a sequence. Returns the updated sequence and\nlist of successful operations (which actually changed something).\n",
                "type": "List (Op a) -> Sequence a -> ( Sequence a, List (Op a) )"
            },
            {
                "name": "before",
                "comment": " Return the entry and its path before the given path in the sequence.\nReturns `Nothing` if there none.\n",
                "type": "Path -> Sequence a -> Maybe ( Path, Entry a )"
            },
            {
                "name": "comparePath",
                "comment": " Compare Paths\n",
                "type": "Path -> Path -> Order"
            },
            {
                "name": "createInsert",
                "comment": " Create an insert operation. Pass it the user identifier, a path and the\nvalue to insert.\n",
                "type": "String -> Path -> a -> Op a"
            },
            {
                "name": "createRemove",
                "comment": " Create a remove operation. Pass it the removing user's identifier, the user\nidentifier of the removed value (ie. to target it in a MVR) and the path.\n",
                "type": "String -> String -> Path -> Op a"
            },
            {
                "name": "decodeOp",
                "comment": " Decode an Op.\n",
                "type": "Decoder a -> Decoder (Op a)"
            },
            {
                "name": "empty",
                "comment": " An empty sequence.\n",
                "type": "Sequence a"
            },
            {
                "name": "encodeOp",
                "comment": " Encoder an Op given an value specific encoder.\n",
                "type": "(a -> Value) -> Op a -> Value"
            },
            {
                "name": "first",
                "comment": " Return the first entry of the sequence and its path.\nIf the sequence is empty returns `Nothing`.\n",
                "type": "Sequence a -> Maybe ( Path, Entry a )"
            },
            {
                "name": "foldl",
                "comment": " Fold a sequence from the left.\n",
                "type": "(Path -> Entry a -> b -> b) -> b -> Sequence a -> b"
            },
            {
                "name": "foldr",
                "comment": " Fold a sequence from the right.\n",
                "type": "(Path -> Entry a -> b -> b) -> b -> Sequence a -> b"
            },
            {
                "name": "get",
                "comment": " Lookup an entry at the given path.\n",
                "type": "Path -> Sequence a -> Maybe (Entry a)"
            },
            {
                "name": "last",
                "comment": " Return the last entry of the sequence and its path.\nIf the sequence is empty returns `Nothing`.\n",
                "type": "Sequence a -> Maybe ( Path, Entry a )"
            },
            {
                "name": "maxPath",
                "comment": " The greatest path possible\n",
                "type": "Path"
            },
            {
                "name": "minPath",
                "comment": " The lowest path possible\n",
                "type": "Path"
            },
            {
                "name": "mvrToList",
                "comment": " Inspect an MVR by turning it into a list of tuples of the user identifier and the `Value`.\n",
                "type": "MVR a -> List ( String, Value a )"
            },
            {
                "name": "path",
                "comment": " Create a path (ie. a non-empty list) given its head and tail.\n",
                "type": "Int -> List Int -> Path"
            }
        ],
        "binops": []
    }
]