├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── _oasis ├── _tags ├── configure ├── crdtml_api.odocl ├── docs ├── .gitkeep ├── Crdt.Immutable.GCounter.html ├── Crdt.Immutable.GSet.html ├── Crdt.Immutable.IntVector.html ├── Crdt.Immutable.ORSet.html ├── Crdt.Immutable.PNCounter.html ├── Crdt.Immutable.USet.html ├── Crdt.Immutable.html ├── Crdt.Mutable.GCounter.html ├── Crdt.Mutable.GSet.html ├── Crdt.Mutable.IntVector.html ├── Crdt.Mutable.ORSet.html ├── Crdt.Mutable.PNCounter.html ├── Crdt.Mutable.USet.html ├── Crdt.Mutable.html ├── Crdt.html ├── IList.html ├── I_GCounter.html ├── I_GSet.Make.html ├── I_GSet.html ├── I_IntVector.html ├── I_ORSet.Make.html ├── I_ORSet.html ├── I_PNCounter.html ├── I_USet.Make.html ├── I_USet.html ├── Immutable_types.Comparable.html ├── Immutable_types.DCounter.html ├── Immutable_types.GSet.html ├── Immutable_types.IVector.html ├── Immutable_types.Mergeable.html ├── Immutable_types.RSet.html ├── Immutable_types.html ├── M_GCounter.html ├── M_GSet.Make.html ├── M_GSet.html ├── M_IntVector.html ├── M_ORSet.Make.html ├── M_ORSet.html ├── M_PNCounter.html ├── M_USet.Make.html ├── M_USet.html ├── Mutable_types.Comparable.html ├── Mutable_types.DCounter.html ├── Mutable_types.GSet.html ├── Mutable_types.IVector.html ├── Mutable_types.Mergeable.html ├── Mutable_types.RSet.html ├── Mutable_types.html ├── html.stamp ├── index.html ├── index_attributes.html ├── index_class_types.html ├── index_classes.html ├── index_exceptions.html ├── index_extensions.html ├── index_methods.html ├── index_module_types.html ├── index_modules.html ├── index_types.html ├── index_values.html ├── style.css ├── type_Crdt.Immutable.GCounter.html ├── type_Crdt.Immutable.GSet.html ├── type_Crdt.Immutable.IntVector.html ├── type_Crdt.Immutable.ORSet.html ├── type_Crdt.Immutable.PNCounter.html ├── type_Crdt.Immutable.USet.html ├── type_Crdt.Immutable.html ├── type_Crdt.Mutable.GCounter.html ├── type_Crdt.Mutable.GSet.html ├── type_Crdt.Mutable.IntVector.html ├── type_Crdt.Mutable.ORSet.html ├── type_Crdt.Mutable.PNCounter.html ├── type_Crdt.Mutable.USet.html ├── type_Crdt.Mutable.html ├── type_Crdt.html ├── type_IList.html ├── type_I_GCounter.html ├── type_I_GSet.Make.html ├── type_I_GSet.html ├── type_I_IntVector.html ├── type_I_ORSet.Make.html ├── type_I_ORSet.html ├── type_I_PNCounter.html ├── type_I_USet.Make.html ├── type_I_USet.html ├── type_Immutable_types.Comparable.html ├── type_Immutable_types.DCounter.html ├── type_Immutable_types.GSet.html ├── type_Immutable_types.IVector.html ├── type_Immutable_types.Mergeable.html ├── type_Immutable_types.RSet.html ├── type_Immutable_types.html ├── type_M_GCounter.html ├── type_M_GSet.Make.html ├── type_M_GSet.html ├── type_M_IntVector.html ├── type_M_ORSet.Make.html ├── type_M_ORSet.html ├── type_M_PNCounter.html ├── type_M_USet.Make.html ├── type_M_USet.html ├── type_Mutable_types.Comparable.html ├── type_Mutable_types.DCounter.html ├── type_Mutable_types.GSet.html ├── type_Mutable_types.IVector.html ├── type_Mutable_types.Mergeable.html ├── type_Mutable_types.RSet.html └── type_Mutable_types.html ├── myocamlbuild.ml ├── opam ├── setup.ml ├── src ├── META ├── crdt.ml ├── crdt.mldylib ├── crdt.mllib ├── immutable │ ├── I_GCounter.ml │ ├── I_GCounter.mli │ ├── I_GSet.ml │ ├── I_GSet.mli │ ├── I_IntVector.ml │ ├── I_IntVector.mli │ ├── I_ORSet.ml │ ├── I_ORSet.mli │ ├── I_PNCounter.ml │ ├── I_PNCounter.mli │ ├── I_USet.ml │ ├── I_USet.mli │ ├── META │ ├── crdt_immutable.mldylib │ ├── crdt_immutable.mllib │ └── immutable_types.ml ├── mutable │ ├── META │ ├── M_GCounter.ml │ ├── M_GCounter.mli │ ├── M_GSet.ml │ ├── M_GSet.mli │ ├── M_IntVector.ml │ ├── M_IntVector.mli │ ├── M_ORSet.ml │ ├── M_ORSet.mli │ ├── M_PNCounter.ml │ ├── M_PNCounter.mli │ ├── M_USet.ml │ ├── M_USet.mli │ ├── crdt_mutable.mldylib │ ├── crdt_mutable.mllib │ └── mutable_types.ml └── util │ ├── IList.ml │ ├── IList.mli │ ├── META │ ├── crdt_util.mldylib │ └── crdt_util.mllib └── test └── .gitkeep /.gitignore: -------------------------------------------------------------------------------- 1 | oasis_clean.sh 2 | qtest.targets.log 3 | !test/.gitkeep 4 | test/ 5 | crdt-ml.* 6 | 7 | ### OCaml ### 8 | *.annot 9 | *.cmo 10 | *.cma 11 | *.cmi 12 | *.a 13 | *.o 14 | *.cmx 15 | *.cmxs 16 | *.cmxa 17 | 18 | # ocamlbuild working directory 19 | _build/ 20 | 21 | # ocamlbuild targets 22 | *.byte 23 | *.native 24 | 25 | # oasis generated files 26 | setup.data 27 | setup.log 28 | 29 | 30 | ### OSX ### 31 | .DS_Store 32 | .AppleDouble 33 | .LSOverride 34 | 35 | # Icon must end with two \r 36 | Icon 37 | 38 | 39 | # Thumbnails 40 | ._* 41 | 42 | # Files that might appear in the root of a volume 43 | .DocumentRevisions-V100 44 | .fseventsd 45 | .Spotlight-V100 46 | .TemporaryItems 47 | .Trashes 48 | .VolumeIcon.icns 49 | 50 | # Directories potentially created on remote AFP share 51 | .AppleDB 52 | .AppleDesktop 53 | Network Trash Folder 54 | Temporary Items 55 | .apdisk 56 | 57 | 58 | ### Vagrant ### 59 | .vagrant/ 60 | 61 | 62 | ### Vim ### 63 | # swap 64 | [._]*.s[a-w][a-z] 65 | [._]s[a-w][a-z] 66 | # session 67 | Session.vim 68 | # temporary 69 | .netrwhist 70 | *~ 71 | # auto-generated tag files 72 | tags 73 | 74 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: a3c674b4239234cbbe53afe090018954) 3 | 4 | SETUP = ocaml setup.ml 5 | 6 | build: setup.data 7 | $(SETUP) -build $(BUILDFLAGS) 8 | 9 | doc: setup.data build 10 | $(SETUP) -doc $(DOCFLAGS) 11 | 12 | test: setup.data build 13 | $(SETUP) -test $(TESTFLAGS) 14 | 15 | all: 16 | $(SETUP) -all $(ALLFLAGS) 17 | 18 | install: setup.data 19 | $(SETUP) -install $(INSTALLFLAGS) 20 | 21 | uninstall: setup.data 22 | $(SETUP) -uninstall $(UNINSTALLFLAGS) 23 | 24 | reinstall: setup.data 25 | $(SETUP) -reinstall $(REINSTALLFLAGS) 26 | 27 | clean: 28 | $(SETUP) -clean $(CLEANFLAGS) 29 | 30 | distclean: 31 | $(SETUP) -distclean $(DISTCLEANFLAGS) 32 | 33 | setup.data: 34 | $(SETUP) -configure $(CONFIGUREFLAGS) 35 | 36 | configure: 37 | $(SETUP) -configure $(CONFIGUREFLAGS) 38 | 39 | .PHONY: build doc test all install uninstall reinstall clean distclean configure 40 | 41 | # OASIS_STOP 42 | -------------------------------------------------------------------------------- /_oasis: -------------------------------------------------------------------------------- 1 | OASISFormat: 0.4 2 | BuildTools: ocamlbuild 3 | Plugins: META (0.4), DevFiles (0.4) 4 | 5 | Name: crdt 6 | Version: 0.10.0 7 | Synopsis: CRDTs - Conflict-Free Replicated Data Types for OCaml 8 | Authors: Borja o'Cook 9 | Maintainers: Borja o'Cook 10 | Homepage: https://github.com/ergl/crdt-ml/ 11 | License: GPL-3 12 | LicenseFile: LICENSE 13 | 14 | Library "crdt_util" 15 | Path: src/util 16 | Modules: IList 17 | 18 | Library "crdt_mutable" 19 | Path: src/mutable 20 | Modules: M_GCounter, M_GSet, M_IntVector, 21 | M_ORSet, M_PNCounter, M_USet, Mutable_types 22 | BuildDepends: crdt_util 23 | 24 | Library "crdt_immutable" 25 | Path: src/immutable 26 | Modules: I_IntVector, I_GCounter, I_PNCounter, 27 | I_GSet, I_ORSet, I_USet, Immutable_types 28 | BuildDepends: crdt_util 29 | 30 | Library "crdt" 31 | Path: src 32 | Modules: Crdt 33 | BuildDepends: crdt_mutable, crdt_immutable 34 | 35 | 36 | AlphaFeatures: ocamlbuild_more_args 37 | Document "crdtml_api" 38 | Type: ocamlbuild (0.4) 39 | BuildTools: ocamldoc 40 | 41 | Title: API reference for Crdt.Mutable and Crdt.Immutable 42 | XOCamlbuildPath: . 43 | XOCamlbuildExtraArgs: 44 | "-docflags '-colorize-code -short-functors -charset utf-8'" 45 | XOCamlbuildLibraries: crdt, crdt_immutable, crdt_mutable 46 | 47 | Test "test_immutable" 48 | TestTools: qtest 49 | WorkingDirectory: test 50 | Command: 51 | qtest -o im_test.ml extract ../src/immutable/*.ml && 52 | ocamlbuild -cflags -warn-error,+26 \ 53 | -use-ocamlfind -package 'qcheck, oUnit, crdt_immutable' \ 54 | im_test.byte && 55 | ./im_test.byte 56 | -------------------------------------------------------------------------------- /_tags: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 0d5a4280a6d5f81faee75a77c11affec) 3 | # Ignore VCS directories, you can use the same kind of rule outside 4 | # OASIS_START/STOP if you want to exclude directories that contains 5 | # useless stuff for the build process 6 | true: annot, bin_annot 7 | <**/.svn>: -traverse 8 | <**/.svn>: not_hygienic 9 | ".bzr": -traverse 10 | ".bzr": not_hygienic 11 | ".hg": -traverse 12 | ".hg": not_hygienic 13 | ".git": -traverse 14 | ".git": not_hygienic 15 | "_darcs": -traverse 16 | "_darcs": not_hygienic 17 | # Library crdt_util 18 | "src/util/crdt_util.cmxs": use_crdt_util 19 | # Library crdt_mutable 20 | "src/mutable/crdt_mutable.cmxs": use_crdt_mutable 21 | : use_crdt_util 22 | # Library crdt_immutable 23 | "src/immutable/crdt_immutable.cmxs": use_crdt_immutable 24 | : use_crdt_util 25 | # Library crdt 26 | "src/crdt.cmxs": use_crdt 27 | : use_crdt_immutable 28 | : use_crdt_mutable 29 | : use_crdt_util 30 | # OASIS_STOP 31 | -------------------------------------------------------------------------------- /configure: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # OASIS_START 4 | # DO NOT EDIT (digest: dc86c2ad450f91ca10c931b6045d0499) 5 | set -e 6 | 7 | FST=true 8 | for i in "$@"; do 9 | if $FST; then 10 | set -- 11 | FST=false 12 | fi 13 | 14 | case $i in 15 | --*=*) 16 | ARG=${i%%=*} 17 | VAL=${i##*=} 18 | set -- "$@" "$ARG" "$VAL" 19 | ;; 20 | *) 21 | set -- "$@" "$i" 22 | ;; 23 | esac 24 | done 25 | 26 | ocaml setup.ml -configure "$@" 27 | # OASIS_STOP 28 | -------------------------------------------------------------------------------- /crdtml_api.odocl: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 0b5106536fe7e55a0de2ee07a5735f75) 3 | src/Crdt 4 | src/immutable/I_IntVector 5 | src/immutable/I_GCounter 6 | src/immutable/I_PNCounter 7 | src/immutable/I_GSet 8 | src/immutable/I_ORSet 9 | src/immutable/I_USet 10 | src/immutable/Immutable_types 11 | src/mutable/M_GCounter 12 | src/mutable/M_GSet 13 | src/mutable/M_IntVector 14 | src/mutable/M_ORSet 15 | src/mutable/M_PNCounter 16 | src/mutable/M_USet 17 | src/mutable/Mutable_types 18 | # OASIS_STOP 19 | -------------------------------------------------------------------------------- /docs/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ergl/crdt-ml/44e474a2346a3b3af8c30fe5f0ce96ae4024fdae/docs/.gitkeep -------------------------------------------------------------------------------- /docs/Crdt.Immutable.GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Immutable.GCounter 29 | 30 | 31 | 35 |

Module Crdt.Immutable.GCounter

36 | 37 |
module GCounter: I_GCounter

38 | 39 |
include Immutable_types.IVector
40 |
41 | An Increment-only counter is a Immutable_types.IVector with type 42 | elt = int
43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Immutable.GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Immutable.GSet 29 | 30 | 31 | 35 |

Module Crdt.Immutable.GSet

36 | 37 |
module GSet: I_GSet

38 | 39 |
module Make (O : Immutable_types.Comparable) : Immutable_types.GSet  with
40 |   type elt = O.t
41 | Creates an grow-only set of elements satisfying 42 | Immutable_types.Comparable 43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Immutable.IntVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt.Immutable.IntVector 28 | 29 | 30 | 33 |

Module Crdt.Immutable.IntVector

34 | 35 |
module IntVector: I_IntVector

36 | 37 |
include Immutable_types.IVector
38 |
39 | A Vector Clock is a Immutable_types.IVector with type 40 | elt = int list
41 |
42 | -------------------------------------------------------------------------------- /docs/Crdt.Immutable.ORSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Immutable.ORSet 29 | 30 | 31 | 35 |

Module Crdt.Immutable.ORSet

36 | 37 |
module ORSet: I_ORSet

38 | 39 |
module Make (O : Immutable_types.Comparable) : Immutable_types.RSet  with
40 |   type elt = O.t
41 | Creates an add / remove set of elements satisfying 42 | Immutable_types.Comparable 43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Immutable.PNCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Immutable.PNCounter 29 | 30 | 31 | 35 |

Module Crdt.Immutable.PNCounter

36 | 37 |
module PNCounter: I_PNCounter

38 | 39 |
include Immutable_types.DCounter
40 |
41 | An Increment / decrement counter is a Immtable_types.IVector 42 | with type elt = int
43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Immutable.USet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt.Immutable.USet 28 | 29 | 30 | 33 |

Module Crdt.Immutable.USet

34 | 35 |
module USet: I_USet

36 | 37 |
module Make (O : Immutable_types.Comparable) : Immutable_types.RSet  with
38 |   type elt = O.t
39 | Creates an add / remove set of elements satisfying 40 | Immutable_types.Comparable 41 |
42 | -------------------------------------------------------------------------------- /docs/Crdt.Immutable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt.Immutable 28 | 29 | 30 | 33 |

Module Crdt.Immutable

34 | 35 |
module Immutable: sig .. end
36 | A collection of immutable CRDTs
37 |
38 |
39 | 40 |
module IntVector: I_IntVector
41 |
module GCounter: I_GCounter
42 |
module PNCounter: I_PNCounter
43 |
module GSet: I_GSet
44 |
module ORSet: I_ORSet
45 |
module USet: I_USet
-------------------------------------------------------------------------------- /docs/Crdt.Mutable.GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Mutable.GCounter 29 | 30 | 31 | 35 |

Module Crdt.Mutable.GCounter

36 | 37 |
module GCounter: M_GCounter

38 | 39 |
include Mutable_types.IVector
40 |
41 | An Increment-only counter is a Mutable_types.IVector with type 42 | elt = int
43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Mutable.GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Mutable.GSet 29 | 30 | 31 | 35 |

Module Crdt.Mutable.GSet

36 | 37 |
module GSet: M_GSet

38 | 39 |
module Make (O : Mutable_types.Comparable) : Mutable_types.GSet  with
40 |   type elt = O.t
41 | Creates an grow-only set of elements satisfying 42 | Mutable_types.Comparable 43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Mutable.IntVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt.Mutable.IntVector 28 | 29 | 30 | 33 |

Module Crdt.Mutable.IntVector

34 | 35 |
module IntVector: M_IntVector

36 | 37 |
include Mutable_types.IVector
38 |
39 | A Vector Clock is a Mutable_types.IVector with type 40 | elt = int list
41 |
42 | -------------------------------------------------------------------------------- /docs/Crdt.Mutable.ORSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Mutable.ORSet 29 | 30 | 31 | 35 |

Module Crdt.Mutable.ORSet

36 | 37 |
module ORSet: M_ORSet

38 | 39 |
module Make (O : Mutable_types.Comparable) : Mutable_types.RSet  with
40 |   type elt = O.t
41 | Creates an add / remove set of elements satisfying 42 | Mutable_types.Comparable 43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Mutable.PNCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Crdt.Mutable.PNCounter 29 | 30 | 31 | 35 |

Module Crdt.Mutable.PNCounter

36 | 37 |
module PNCounter: M_PNCounter

38 | 39 |
include Mutable_types.DCounter
40 |
41 | An Increment / decrement counter is a Mutable_types.IVector 42 | with type elt = int
43 |
44 | -------------------------------------------------------------------------------- /docs/Crdt.Mutable.USet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt.Mutable.USet 28 | 29 | 30 | 33 |

Module Crdt.Mutable.USet

34 | 35 |
module USet: M_USet

36 | 37 |
module Make (O : Mutable_types.Comparable) : Mutable_types.RSet  with
38 |   type elt = O.t
39 | Creates an add / remove set of elements satisfying 40 | Mutable_types.Comparable 41 |
42 | -------------------------------------------------------------------------------- /docs/Crdt.Mutable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt.Mutable 28 | 29 | 30 | 33 |

Module Crdt.Mutable

34 | 35 |
module Mutable: sig .. end
36 | A collection of mutable CRDTs
37 |
38 |
39 | 40 |
module IntVector: M_IntVector
41 |
module GCounter: M_GCounter
42 |
module PNCounter: M_PNCounter
43 |
module GSet: M_GSet
44 |
module ORSet: M_ORSet
45 |
module USet: M_USet
-------------------------------------------------------------------------------- /docs/Crdt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Crdt 28 | 29 | 30 | 33 |

Module Crdt

34 | 35 |
module Crdt: sig .. end
36 | A collection of mutable and immutable CRDTs. 37 |

38 | 39 | This module is meant to be opened to use both mutable and immutable 40 | structures in the same codebase. To use, for example, and ORSet, you can 41 | choose to use either Mutable.ORSet or Immutable.ORSet.
42 |

43 |
44 | 45 |
module Mutable: sig .. end
46 | A collection of mutable CRDTs 47 |
48 | 49 |
module Immutable: sig .. end
50 | A collection of immutable CRDTs 51 |
52 | -------------------------------------------------------------------------------- /docs/IList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | IList 21 | 22 | 23 | 26 |

Module IList

27 | 28 |
module IList: sig .. end
29 | Helper List library that supports dynamic padding for higher-order 30 | functions operating on lists of different length.
31 |
32 |
33 | 34 |
val incr_nth : int list -> int -> int list
35 | incr_nth l n adds one to the nth element of l.
36 |
37 | 38 |
val fill_map2 : (int -> int -> int) -> int list -> int list -> int list
39 | fill_map2 f l l' padds with zeros the smaller list before applying f.
40 |
41 | 42 |
val fill_fold_left2 : (int -> int -> int -> int) -> int -> int list -> int list -> int
43 | fill_fold_left2 f l l' padds with zeros the smaller list before applying f.
44 |
45 | -------------------------------------------------------------------------------- /docs/I_GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | I_GCounter 29 | 30 | 31 | 35 |

Module I_GCounter

36 | 37 |
module I_GCounter: sig .. end
38 | Increment-only counters. 39 |

40 | 41 | Conceptually the same as a I_IntVector. The only difference is 42 | that Immutable_types.IVector.query t returns the sum of all the 43 | elements in the vector.
44 |

45 |
46 | 47 |
include Immutable_types.IVector
48 |
49 | An Increment-only counter is a Immutable_types.IVector with type 50 | elt = int
51 |
52 | -------------------------------------------------------------------------------- /docs/Immutable_types.Comparable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Immutable_types.Comparable 28 | 29 | 30 | 33 |

Module type Immutable_types.Comparable

34 | 35 |
module type Comparable = sig .. end
36 | Comparable types. All elements in a set must satisfy this property. 37 |

38 | 39 | Same as the built-in Set.OrderedType, this type includes a t and a 40 | compare : t -> t -> int function. See Pervasives.compare
41 |

42 |
43 | 44 |
include Set.OrderedType
45 | -------------------------------------------------------------------------------- /docs/Immutable_types.RSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Immutable_types.RSet 28 | 29 | 30 | 33 |

Module type Immutable_types.RSet

34 | 35 |
module type RSet = sig .. end
36 | Add and remove set type. Supports merging, adding and lookup operations.
37 |
38 |
39 | 40 |
include Immutable_types.GSet
41 | 42 |
val remove : elt -> t -> t
43 | remove el t removes el from t only if el is in t. 44 | Returns t otherwise.
45 |
46 | -------------------------------------------------------------------------------- /docs/M_GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | M_GCounter 29 | 30 | 31 | 35 |

Module M_GCounter

36 | 37 |
module M_GCounter: sig .. end
38 | Increment-only counters. 39 |

40 | 41 | Conceptually the same as a M_IntVector. The only difference is 42 | that Mutable_types.IVector.query t returns the sum of all the 43 | elements in the vector.
44 |

45 |
46 | 47 |
include Mutable_types.IVector
48 |
49 | An Increment-only counter is a Mutable_types.IVector with type 50 | elt = int
51 |
52 | -------------------------------------------------------------------------------- /docs/M_GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | M_GSet 29 | 30 | 31 | 35 |

Module M_GSet

36 | 37 |
module M_GSet: sig .. end
38 | Grow-Only sets. 39 |

40 | 41 | Supports add, lookup and merge operations. 42 | See Mutable_types.GSet
43 |

44 |
45 | 46 |
module Make (O : Mutable_types.Comparable) : Mutable_types.GSet  with
47 |   type elt = O.t
48 | Creates an grow-only set of elements satisfying 49 | Mutable_types.Comparable 50 |
51 | -------------------------------------------------------------------------------- /docs/Mutable_types.Comparable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Mutable_types.Comparable 28 | 29 | 30 | 33 |

Module type Mutable_types.Comparable

34 | 35 |
module type Comparable = sig .. end
36 | Comparable types. All elements in a set must satisfy this property. 37 |

38 | 39 | Same as the built-in Set.OrderedType, this type includes a t and a 40 | compare : t -> t -> int function. See Pervasives.compare
41 |

42 |
43 | 44 |
include Set.OrderedType
45 | -------------------------------------------------------------------------------- /docs/Mutable_types.DCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | Mutable_types.DCounter 29 | 30 | 31 | 35 |

Module type Mutable_types.DCounter

36 | 37 |
module type DCounter = sig .. end
38 | Increment / decrement counter type. Supports merging, incrementing and 39 | decrementing. 40 |

41 | 42 | The elt type (included from IVector must be supplied when including).
43 |

44 |
45 | 46 |
include Mutable_types.IVector
47 | 48 |
val decr : t -> unit
49 | decr t decrements the position associated with the numsite of t. 50 | See M_IntVector for more information on numsites.
51 |
52 | -------------------------------------------------------------------------------- /docs/Mutable_types.RSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | Mutable_types.RSet 28 | 29 | 30 | 33 |

Module type Mutable_types.RSet

34 | 35 |
module type RSet = sig .. end
36 | Add and remove set type. Supports merging, adding and lookup operations.
37 |
38 |
39 | 40 |
include Mutable_types.GSet
41 | 42 |
val remove : elt -> t -> unit
43 | remove el t removes el from t only if el is in t. 44 | Does nothing otherwise.
45 |
46 | -------------------------------------------------------------------------------- /docs/html.stamp: -------------------------------------------------------------------------------- 1 | 4fc9f632cf8cd947649e1730d9b4e60b -------------------------------------------------------------------------------- /docs/index_attributes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Index of class attributes 25 | 26 | 27 | 29 |

Index of class attributes

30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /docs/index_class_types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Index of class types 25 | 26 | 27 | 29 |

Index of class types

30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /docs/index_classes.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Index of classes 25 | 26 | 27 | 29 |

Index of classes

30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /docs/index_exceptions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Index of exceptions 25 | 26 | 27 | 29 |

Index of exceptions

30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /docs/index_extensions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Index of extensions 25 | 26 | 27 | 29 |

Index of extensions

30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /docs/index_methods.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Index of class methods 25 | 26 | 27 | 29 |

Index of class methods

30 | 31 |
32 | 33 | -------------------------------------------------------------------------------- /docs/style.css: -------------------------------------------------------------------------------- 1 | .keyword { font-weight : bold ; color : Red } 2 | .keywordsign { color : #C04600 } 3 | .superscript { font-size : 4 } 4 | .subscript { font-size : 4 } 5 | .comment { color : Green } 6 | .constructor { color : Blue } 7 | .type { color : #5C6585 } 8 | .string { color : Maroon } 9 | .warning { color : Red ; font-weight : bold } 10 | .info { margin-left : 3em; margin-right: 3em } 11 | .param_info { margin-top: 4px; margin-left : 3em; margin-right : 3em } 12 | .code { color : #465F91 ; } 13 | .typetable { border-style : hidden } 14 | .paramstable { border-style : hidden ; padding: 5pt 5pt} 15 | tr { background-color : White } 16 | td.typefieldcomment { background-color : #FFFFFF ; font-size: smaller ;} 17 | div.sig_block {margin-left: 2em} 18 | *:target { background: yellow; } 19 | body {font: 13px sans-serif; color: black; text-align: left; padding: 5px; margin: 0} 20 | h1 { font-size : 20pt ; text-align: center; } 21 | h2 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ;padding: 2px; } 22 | h3 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90DDFF ;padding: 2px; } 23 | h4 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90EDFF ;padding: 2px; } 24 | h5 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90FDFF ;padding: 2px; } 25 | h6 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #90BDFF ; padding: 2px; } 26 | div.h7 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #E0FFFF ; padding: 2px; } 27 | div.h8 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #F0FFFF ; padding: 2px; } 28 | div.h9 { font-size : 20pt ; border: 1px solid #000000; margin-top: 5px; margin-bottom: 2px;text-align: center; background-color: #FFFFFF ; padding: 2px; } 29 | a {color: #416DFF; text-decoration: none} 30 | a:hover {background-color: #ddd; text-decoration: underline} 31 | pre { margin-bottom: 4px; font-family: monospace; } 32 | pre.verbatim, pre.codepre { } 33 | .indextable {border: 1px #ddd solid; border-collapse: collapse} 34 | .indextable td, .indextable th {border: 1px #ddd solid; min-width: 80px} 35 | .indextable td.module {background-color: #eee ; padding-left: 2px; padding-right: 2px} 36 | .indextable td.module a {color: 4E6272; text-decoration: none; display: block; width: 100%} 37 | .indextable td.module a:hover {text-decoration: underline; background-color: transparent} 38 | .deprecated {color: #888; font-style: italic} 39 | .indextable tr td div.info { margin-left: 2px; margin-right: 2px } 40 | ul.indexlist { margin-left: 0; padding-left: 0;} 41 | ul.indexlist li { list-style-type: none ; margin-left: 0; padding-left: 0; } -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable.GCounter 24 | 25 | 26 | (module I_GCounter) -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable.GSet 24 | 25 | 26 | (module I_GSet) -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.IntVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable.IntVector 24 | 25 | 26 | (module I_IntVector) -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.ORSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable.ORSet 24 | 25 | 26 | (module I_ORSet) -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.PNCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable.PNCounter 24 | 25 | 26 | (module I_PNCounter) -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.USet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable.USet 24 | 25 | 26 | (module I_USet) -------------------------------------------------------------------------------- /docs/type_Crdt.Immutable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Immutable 24 | 25 | 26 | sig
27 |   module IntVector = I_IntVector
28 |   module GCounter = I_GCounter
29 |   module PNCounter = I_PNCounter
30 |   module GSet = I_GSet
31 |   module ORSet = I_ORSet
32 |   module USet = I_USet
33 | end
-------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable.GCounter 24 | 25 | 26 | (module M_GCounter) -------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable.GSet 24 | 25 | 26 | (module M_GSet) -------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.IntVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable.IntVector 24 | 25 | 26 | (module M_IntVector) -------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.ORSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable.ORSet 24 | 25 | 26 | (module M_ORSet) -------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.PNCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable.PNCounter 24 | 25 | 26 | (module M_PNCounter) -------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.USet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable.USet 24 | 25 | 26 | (module M_USet) -------------------------------------------------------------------------------- /docs/type_Crdt.Mutable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt.Mutable 24 | 25 | 26 | sig
27 |   module IntVector = M_IntVector
28 |   module GCounter = M_GCounter
29 |   module PNCounter = M_PNCounter
30 |   module GSet = M_GSet
31 |   module ORSet = M_ORSet
32 |   module USet = M_USet
33 | end
-------------------------------------------------------------------------------- /docs/type_Crdt.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Crdt 24 | 25 | 26 | sig  end -------------------------------------------------------------------------------- /docs/type_IList.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | IList 17 | 18 | 19 | sig
20 |   val incr_nth : int list -> int -> int list
21 |   val fill_map2 : (int -> int -> int) -> int list -> int list -> int list
22 |   val fill_fold_left2 :
23 |     (int -> int -> int -> int) -> int -> int list -> int list -> int
24 | end
-------------------------------------------------------------------------------- /docs/type_I_GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | I_GCounter 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt = int
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> t
34 | end
-------------------------------------------------------------------------------- /docs/type_I_GSet.Make.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | I_GSet.Make 24 | 25 | 26 | functor (O : Immutable_types.Comparable->
27 |   sig
28 |     type t
29 |     val make : unit -> t
30 |     val merge : t -> t -> t
31 |     type elt = O.t
32 |     val add : elt -> t -> t
33 |     val value : t -> elt list
34 |     val lookup : elt -> t -> bool
35 |   end
-------------------------------------------------------------------------------- /docs/type_I_IntVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | I_IntVector 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt = int list
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> t
34 | end
-------------------------------------------------------------------------------- /docs/type_I_ORSet.Make.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | I_ORSet.Make 24 | 25 | 26 | functor (O : Immutable_types.Comparable->
27 |   sig
28 |     type t
29 |     val make : unit -> t
30 |     val merge : t -> t -> t
31 |     type elt = O.t
32 |     val add : elt -> t -> t
33 |     val value : t -> elt list
34 |     val lookup : elt -> t -> bool
35 |     val remove : elt -> t -> t
36 |   end
-------------------------------------------------------------------------------- /docs/type_I_PNCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | I_PNCounter 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt = int
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> t
34 |   val decr : t -> t
35 | end
-------------------------------------------------------------------------------- /docs/type_I_USet.Make.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | I_USet.Make 24 | 25 | 26 | functor (O : Immutable_types.Comparable->
27 |   sig
28 |     type t
29 |     val make : unit -> t
30 |     val merge : t -> t -> t
31 |     type elt = O.t
32 |     val add : elt -> t -> t
33 |     val value : t -> elt list
34 |     val lookup : elt -> t -> bool
35 |     val remove : elt -> t -> t
36 |   end
-------------------------------------------------------------------------------- /docs/type_Immutable_types.Comparable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types.Comparable 24 | 25 | 26 | sig type t val compare : t -> t -> int end -------------------------------------------------------------------------------- /docs/type_Immutable_types.DCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types.DCounter 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> t
34 |   val decr : t -> t
35 | end
-------------------------------------------------------------------------------- /docs/type_Immutable_types.GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types.GSet 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt
31 |   val add : Immutable_types.GSet.elt -> t -> t
32 |   val value : t -> Immutable_types.GSet.elt list
33 |   val lookup : Immutable_types.GSet.elt -> t -> bool
34 | end
-------------------------------------------------------------------------------- /docs/type_Immutable_types.IVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types.IVector 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt
31 |   val make_in_range : int -> t
32 |   val query : t -> Immutable_types.IVector.elt
33 |   val incr : t -> t
34 | end
-------------------------------------------------------------------------------- /docs/type_Immutable_types.Mergeable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types.Mergeable 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> Immutable_types.Mergeable.t
29 |   val merge :
30 |     Immutable_types.Mergeable.t ->
31 |     Immutable_types.Mergeable.t -> Immutable_types.Mergeable.t
32 | end
-------------------------------------------------------------------------------- /docs/type_Immutable_types.RSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types.RSet 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> t
30 |   type elt
31 |   val add : elt -> t -> t
32 |   val value : t -> elt list
33 |   val lookup : elt -> t -> bool
34 |   val remove : elt -> t -> t
35 | end
-------------------------------------------------------------------------------- /docs/type_Immutable_types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Immutable_types 24 | 25 | 26 | sig  end -------------------------------------------------------------------------------- /docs/type_M_GCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | M_GCounter 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt = int
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> unit
34 | end
-------------------------------------------------------------------------------- /docs/type_M_GSet.Make.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | M_GSet.Make 24 | 25 | 26 | functor (O : Mutable_types.Comparable->
27 |   sig
28 |     type t
29 |     val make : unit -> t
30 |     val merge : t -> t -> unit
31 |     type elt = O.t
32 |     val add : elt -> t -> unit
33 |     val value : t -> elt list
34 |     val lookup : elt -> t -> bool
35 |   end
-------------------------------------------------------------------------------- /docs/type_M_IntVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | M_IntVector 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt = int list
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> unit
34 | end
-------------------------------------------------------------------------------- /docs/type_M_ORSet.Make.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | M_ORSet.Make 24 | 25 | 26 | functor (O : Mutable_types.Comparable->
27 |   sig
28 |     type t
29 |     val make : unit -> t
30 |     val merge : t -> t -> unit
31 |     type elt = O.t
32 |     val add : elt -> t -> unit
33 |     val value : t -> elt list
34 |     val lookup : elt -> t -> bool
35 |     val remove : elt -> t -> unit
36 |   end
-------------------------------------------------------------------------------- /docs/type_M_PNCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | M_PNCounter 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt = int
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> unit
34 |   val decr : t -> unit
35 | end
-------------------------------------------------------------------------------- /docs/type_M_USet.Make.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | M_USet.Make 24 | 25 | 26 | functor (O : Mutable_types.Comparable->
27 |   sig
28 |     type t
29 |     val make : unit -> t
30 |     val merge : t -> t -> unit
31 |     type elt = O.t
32 |     val add : elt -> t -> unit
33 |     val value : t -> elt list
34 |     val lookup : elt -> t -> bool
35 |     val remove : elt -> t -> unit
36 |   end
-------------------------------------------------------------------------------- /docs/type_Mutable_types.Comparable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types.Comparable 24 | 25 | 26 | sig type t val compare : t -> t -> int end -------------------------------------------------------------------------------- /docs/type_Mutable_types.DCounter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types.DCounter 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt
31 |   val make_in_range : int -> t
32 |   val query : t -> elt
33 |   val incr : t -> unit
34 |   val decr : t -> unit
35 | end
-------------------------------------------------------------------------------- /docs/type_Mutable_types.GSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types.GSet 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt
31 |   val add : Mutable_types.GSet.elt -> t -> unit
32 |   val value : t -> Mutable_types.GSet.elt list
33 |   val lookup : Mutable_types.GSet.elt -> t -> bool
34 | end
-------------------------------------------------------------------------------- /docs/type_Mutable_types.IVector.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types.IVector 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt
31 |   val make_in_range : int -> t
32 |   val query : t -> Mutable_types.IVector.elt
33 |   val incr : t -> unit
34 | end
-------------------------------------------------------------------------------- /docs/type_Mutable_types.Mergeable.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types.Mergeable 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> Mutable_types.Mergeable.t
29 |   val merge : Mutable_types.Mergeable.t -> Mutable_types.Mergeable.t -> unit
30 | end
-------------------------------------------------------------------------------- /docs/type_Mutable_types.RSet.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types.RSet 24 | 25 | 26 | sig
27 |   type t
28 |   val make : unit -> t
29 |   val merge : t -> t -> unit
30 |   type elt
31 |   val add : elt -> t -> unit
32 |   val value : t -> elt list
33 |   val lookup : elt -> t -> bool
34 |   val remove : elt -> t -> unit
35 | end
-------------------------------------------------------------------------------- /docs/type_Mutable_types.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Mutable_types 24 | 25 | 26 | sig  end -------------------------------------------------------------------------------- /opam: -------------------------------------------------------------------------------- 1 | opam-version: "1.2" 2 | maintainer: "Borja o'Cook " 3 | authors: "Borja o'Cook " 4 | homepage: "https://github.com/ergl/crdt-ml/" 5 | bug-reports: "https://github.com/ergl/crdt-ml/issues" 6 | dev-repo: "https://github.com/ergl/crdt-ml.git" 7 | license: "GPL-3" 8 | build: [ 9 | ["ocaml" "setup.ml" "-configure" "--prefix" prefix] 10 | ["ocaml" "setup.ml" "-build"] 11 | ] 12 | install: ["ocaml" "setup.ml" "-install"] 13 | build-test: [ 14 | ["ocaml" "setup.ml" "-configure" "--enable-tests"] 15 | ["ocaml" "setup.ml" "-build"] 16 | ["ocaml" "setup.ml" "-test"] 17 | ] 18 | build-doc: ["ocaml" "setup.ml" "-doc"] 19 | remove: [ 20 | ["ocamlfind" "remove" "crdt"] 21 | ["ocamlfind" "remove" "crdt_immutable"] 22 | ["ocamlfind" "remove" "crdt_mutable"] 23 | ["ocamlfind" "remove" "crdt_util"] 24 | ] 25 | depends: [ 26 | "ocamlbuild" {build} 27 | "ocamlfind" {build} 28 | "qtest" {test} 29 | ] 30 | available: [ocaml-version >= "4.02.0"] 31 | -------------------------------------------------------------------------------- /src/META: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 89c90b03c81e8c4d972c57c2248b9272) 3 | version = "0.10.0" 4 | description = "CRDTs - OCaml style" 5 | requires = "crdt_mutable crdt_immutable" 6 | archive(byte) = "crdt.cma" 7 | archive(byte, plugin) = "crdt.cma" 8 | archive(native) = "crdt.cmxa" 9 | archive(native, plugin) = "crdt.cmxs" 10 | exists_if = "crdt.cma" 11 | # OASIS_STOP 12 | 13 | -------------------------------------------------------------------------------- /src/crdt.ml: -------------------------------------------------------------------------------- 1 | (** A collection of mutable and immutable CRDTs. 2 | 3 | This module is meant to be opened to use both mutable and immutable 4 | structures in the same codebase. To use, for example, and [ORSet], you can 5 | choose to use either [Mutable.ORSet] or [Immutable.ORSet]. *) 6 | 7 | (** A collection of mutable CRDTs *) 8 | module Mutable = struct 9 | module IntVector = M_IntVector 10 | module GCounter = M_GCounter 11 | module PNCounter = M_PNCounter 12 | module GSet = M_GSet 13 | module ORSet = M_ORSet 14 | module USet = M_USet 15 | end 16 | 17 | (** A collection of immutable CRDTs *) 18 | module Immutable = struct 19 | module IntVector = I_IntVector 20 | module GCounter = I_GCounter 21 | module PNCounter = I_PNCounter 22 | module GSet = I_GSet 23 | module ORSet = I_ORSet 24 | module USet = I_USet 25 | end 26 | -------------------------------------------------------------------------------- /src/crdt.mldylib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 3e46b9a9129401fb7f961edf9b028ae2) 3 | Crdt 4 | # OASIS_STOP 5 | -------------------------------------------------------------------------------- /src/crdt.mllib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 3e46b9a9129401fb7f961edf9b028ae2) 3 | Crdt 4 | # OASIS_STOP 5 | -------------------------------------------------------------------------------- /src/immutable/I_GCounter.ml: -------------------------------------------------------------------------------- 1 | (*$inject 2 | let small = I_GCounter.query 3 | let gen : I_GCounter.t QCheck.Gen.t = fun r -> I_GCounter.make () 4 | let gctr : I_GCounter.t QCheck.arbitrary = QCheck.make ~small gen 5 | *) 6 | 7 | type elt = int 8 | type t = (elt * int list) 9 | 10 | let make_in_range modulo = 11 | let _ = Random.self_init () in 12 | let numsite = Random.int modulo in 13 | (numsite, Array.(make (numsite + 1) 0 |> to_list)) 14 | 15 | let make () = make_in_range 11 16 | 17 | let query (_, pl) = List.fold_left (+) 0 pl 18 | 19 | (*$QR incr 20 | (* Updates monotonically advance upwards *) 21 | gctr (fun a -> 22 | query a <= query (incr a) 23 | ) 24 | *) 25 | let incr (id, payload) = 26 | (id, IList.incr_nth payload id) 27 | 28 | (*$QR merge 29 | (* GCounter.merge is commutative, idempotent and associative *) 30 | Q.(triple gctr gctr gctr) (fun (a, b, c) -> 31 | (merge a b |> query) = (merge b a |> query) && 32 | (merge a a |> query) = (query a) && 33 | (merge a (merge b c) |> query) = (merge (merge a b) c |> query)) 34 | *) 35 | let merge (id, pl) (_, pl') = 36 | (id, IList.fill_map2 max pl pl') 37 | -------------------------------------------------------------------------------- /src/immutable/I_GCounter.mli: -------------------------------------------------------------------------------- 1 | (** Increment-only counters. 2 | 3 | Conceptually the same as a {!module:I_IntVector}. The only difference is 4 | that {!val:Immutable_types.IVector.query} [t] returns the sum of all the 5 | elements in the vector. *) 6 | 7 | (** An Increment-only counter is a {!module:Immutable_types.IVector} with type 8 | [elt = int]*) 9 | include Immutable_types.IVector with type elt = int 10 | -------------------------------------------------------------------------------- /src/immutable/I_GSet.ml: -------------------------------------------------------------------------------- 1 | open Immutable_types 2 | 3 | (*$inject 4 | module StrGSet = I_GSet.Make(struct type t = string let compare = compare end) 5 | 6 | let small t = List.length (StrGSet.value t) 7 | 8 | let print t = 9 | let v = StrGSet.value t in 10 | if List.length v = 0 then "empty_gset" 11 | else String.concat " " v 12 | 13 | let gen : StrGSet.t QCheck.Gen.t = fun r -> StrGSet.make () 14 | let gset : StrGSet.t QCheck.arbitrary = QCheck.make ~small ~print gen 15 | *) 16 | 17 | module Make (O : Comparable) = struct (*$< StrGSet *) 18 | module ISet = Set.Make (O) 19 | 20 | type t = ISet.t 21 | type elt = O.t 22 | 23 | let make () = ISet.empty 24 | 25 | let value = ISet.elements 26 | 27 | (*$QR add 28 | (* Adds monotonically advance upwards *) 29 | Q.(pair string gset) (fun (s, a) -> 30 | value a <= value (add s a) 31 | ) 32 | *) 33 | let add = ISet.add 34 | 35 | (*$QR lookup 36 | (* Lookup of s in add s always returns true *) 37 | Q.(pair string gset) (fun (s, a) -> 38 | lookup s (add s a) = true 39 | ) 40 | *) 41 | let lookup = ISet.mem 42 | 43 | (*$QR merge 44 | Q.(triple gset gset gset) (fun (a, b, c) -> 45 | (merge a b |> value) = (merge b a |> value) && 46 | (merge a a |> value) = (value a) && 47 | (merge a (merge b c) |> value) = (merge (merge a b) c |> value)) 48 | *) 49 | let merge = ISet.union 50 | end (*$>*) 51 | -------------------------------------------------------------------------------- /src/immutable/I_GSet.mli: -------------------------------------------------------------------------------- 1 | (** Grow-Only sets. 2 | 3 | Supports [add], [lookup] and [merge] operations. 4 | See {!module:Immutable_types.GSet} *) 5 | 6 | 7 | (** Creates an grow-only set of elements satisfying 8 | {!module:Immutable_types.Comparable}*) 9 | module Make (O : Immutable_types.Comparable) : Immutable_types.GSet with 10 | type elt = O.t 11 | -------------------------------------------------------------------------------- /src/immutable/I_IntVector.ml: -------------------------------------------------------------------------------- 1 | (*$inject 2 | let gen : I_IntVector.t QCheck.Gen.t = fun r -> I_IntVector.make () 3 | let ivt : I_IntVector.t QCheck.arbitrary = QCheck.make gen 4 | *) 5 | 6 | type id = int 7 | type elt = int list 8 | type t = (id * elt) 9 | 10 | (*$QR make_in_range 11 | Q.(int_range 1 10000) (fun i -> 12 | let size = make_in_range i |> query |> List.length 13 | in 14 | size > 0 && size <= i 15 | ) 16 | *) 17 | let make_in_range modulo = 18 | let _ = Random.self_init () in 19 | let numsite = Random.int modulo in 20 | (numsite, Array.(make (numsite + 1) 0 |> to_list)) 21 | 22 | (*$QR make 23 | Q.unit (fun () -> 24 | let size = make () |> query |> List.length in 25 | size > 0 && size <= 11) 26 | *) 27 | let make () = make_in_range 11 28 | 29 | let query = snd 30 | 31 | (*$QR incr 32 | (* Updates monotonically advance upwards *) 33 | ivt (fun a -> 34 | query a <= query (incr a) 35 | ) 36 | *) 37 | let incr (id, payload) = 38 | (id, IList.incr_nth payload id) 39 | 40 | (*$QR merge 41 | (* IntVector.merge is commutative, idempotent and associative *) 42 | Q.(triple ivt ivt ivt) (fun (a, b, c) -> 43 | (merge a b |> query) = (merge b a |> query) && 44 | (merge a a |> query) = (query a) && 45 | (merge a (merge b c) |> query) = (merge (merge a b) c |> query)) 46 | *) 47 | let merge (id, payload) (_, payload') = 48 | (id, IList.fill_map2 max payload payload') 49 | -------------------------------------------------------------------------------- /src/immutable/I_IntVector.mli: -------------------------------------------------------------------------------- 1 | (** Vector Clocks. 2 | 3 | An integer vector where each replica is restricted to incrementing its own 4 | index [i]. This index is generated at random and assigned to a [numsite] 5 | value when calling [make ()] or [make_in_range n]. All subsequent calls to 6 | update operations will only act on the position noted by [numsite]. 7 | 8 | By default, {!val:Immutable_types.Mergeable.make} just calls 9 | {!val:Immutable_types.IVector.make_in_range} [n] with [n = 11]. You can 10 | override this by calling [make_in_range] directly. *) 11 | 12 | (** A Vector Clock is a {!module:Immutable_types.IVector} with type 13 | [elt = int list]*) 14 | include Immutable_types.IVector with type elt = int list 15 | -------------------------------------------------------------------------------- /src/immutable/I_ORSet.ml: -------------------------------------------------------------------------------- 1 | open Immutable_types 2 | 3 | (*$inject 4 | module StrORSet = I_ORSet.Make(struct type t = string let compare = compare end) 5 | 6 | let small t = List.length (StrORSet.value t) 7 | 8 | let print t = 9 | let v = StrORSet.value t in 10 | if List.length v = 0 then "empty_orset" 11 | else String.concat " " v 12 | 13 | let gen : StrORSet.t QCheck.Gen.t = fun r -> StrORSet.make () 14 | let orset : StrORSet.t QCheck.arbitrary = QCheck.make ~small ~print gen 15 | *) 16 | 17 | module Make (O : Comparable) = struct (*$< StrORSet *) 18 | module ISet = Set.Make (struct 19 | type t = (int * O.t) 20 | let compare (a, b) (c, d) = let tmp = compare a c in 21 | if tmp <> 0 then tmp else O.compare b d 22 | end) 23 | 24 | let _ = Random.self_init () 25 | 26 | type t = (ISet.t * ISet.t) 27 | type elt = O.t 28 | 29 | let unique () = Random.bits () 30 | 31 | let make () = let d = ISet.empty in (d, d) 32 | 33 | (*$QR add 34 | (* Adds monotonically advance upwards *) 35 | Q.(pair string orset) (fun (s, a) -> 36 | value a <= value @@ add s a 37 | ) 38 | *) 39 | let add el (a, r) = 40 | (ISet.add (unique (), el) a, r) 41 | 42 | let value (a, r) = ISet.diff a r 43 | |> ISet.elements 44 | |> List.map snd 45 | |> List.sort_uniq O.compare 46 | 47 | (*$QR lookup 48 | (* Lookup of s in add s always returns true *) 49 | Q.(pair string orset) (fun (s, a) -> 50 | lookup s (add s a) = true 51 | ) 52 | *) 53 | let lookup el (a, r) = ISet.diff a r 54 | |> ISet.exists (fun (_, el') -> el = el') 55 | 56 | (*$QR remove 57 | (* Removes monotonically advance downwards *) 58 | Q.(pair string orset) (fun (s, a) -> 59 | value (add s a) >= value (remove s a) 60 | ) 61 | *) 62 | let remove el s = 63 | if lookup el s then begin 64 | let (a, r) = s in 65 | let in_a = ISet.filter (fun (_, el') -> el = el') a in 66 | (a, ISet.union in_a r) 67 | end else s 68 | 69 | (*$QR merge 70 | Q.(triple orset orset orset) (fun (a, b, c) -> 71 | (merge a b |> value) = (merge b a |> value) && 72 | (merge a a |> value) = (value a) && 73 | (merge a (merge b c) |> value) = (merge (merge a b) c |> value)) 74 | *) 75 | let merge (a, r) (a', r') = 76 | (ISet.union a a', ISet.union r r') 77 | 78 | end (*$>*) 79 | -------------------------------------------------------------------------------- /src/immutable/I_ORSet.mli: -------------------------------------------------------------------------------- 1 | (** Observed-Remove set. 2 | 3 | Supports [add], [remove], [lookup] and [merge] operations. 4 | See {!module:Immutable_types.RSet}. Contains two separate instances of 5 | a regular [Map], one for adding ([add_s]) and the other for removing 6 | ([remove_s]). 7 | 8 | [add el t] adds [(unique (), el)] to [add_s], where unique is the result of 9 | calling 10 | {{:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Random.html#VALbits} 11 | Random.bits}. This may or may not be enough entropy for your use case. 12 | 13 | [remove el t] adds all [{(u, el) | ∃ u : (u, el) ∈ add_s}] to [remove_s] 14 | 15 | Both [lookup] and [value] operate on the set difference [add_s \ remove_s]. 16 | 17 | [merge a b] calls merges [add_s_a] with [add_s_b] and the same for [b] *) 18 | 19 | (** Creates an add / remove set of elements satisfying 20 | {!modtype:Immutable_types.Comparable}*) 21 | module Make (O : Immutable_types.Comparable) : Immutable_types.RSet with 22 | type elt = O.t 23 | -------------------------------------------------------------------------------- /src/immutable/I_PNCounter.ml: -------------------------------------------------------------------------------- 1 | (*$inject 2 | let small = I_PNCounter.query 3 | let gen : I_PNCounter.t QCheck.Gen.t = fun r -> I_PNCounter.make () 4 | let pnctr : I_PNCounter.t QCheck.arbitrary = QCheck.make ~small gen 5 | *) 6 | 7 | type elt = int 8 | type payload = (int list * int list) 9 | type t = (elt * payload) 10 | 11 | let make_in_range modulo = 12 | let _ = Random.self_init () in 13 | let numsite = Random.int modulo in 14 | let payload = Array.(make (numsite + 1) 0 |> to_list) in 15 | (numsite, (payload, payload)) 16 | 17 | let make () = make_in_range 11 18 | 19 | let query (_, (a, r)) = 20 | IList.fill_fold_left2 (fun acc a r -> acc + (a - r)) 0 a r 21 | 22 | (*$QR incr; decr 23 | (* Combinations of incr and decr form a noop *) 24 | pnctr (fun a -> 25 | (decr a |> incr |> query) = (incr a |> decr |> query) && 26 | (incr a |> decr |> query) = query a 27 | ) 28 | *) 29 | 30 | (*$QR incr 31 | (* Increments monotonically advance upwards *) 32 | pnctr (fun a -> 33 | query a <= query (incr a) 34 | ) 35 | *) 36 | let incr (id, (a, r)) = 37 | (id, (IList.incr_nth a id, r)) 38 | 39 | (*$QR decr 40 | (* Decrements monotonically advance downwards *) 41 | pnctr (fun a -> 42 | query a >= query (decr a) 43 | ) 44 | *) 45 | let decr (id, (a, r)) = 46 | (id, (a, IList.incr_nth r id)) 47 | 48 | (*$QR merge 49 | (* PNCounter.merge is commutative, idempotent and associative *) 50 | Q.(triple pnctr pnctr pnctr) (fun (a, b, c) -> 51 | (merge a b |> query) = (merge b a |> query) && 52 | (merge a a |> query) = (query a) && 53 | (merge a (merge b c) |> query) = (merge (merge a b) c |> query)) 54 | *) 55 | let merge (id, (a, r)) (_, (a', r')) = 56 | let max' a b = IList.fill_map2 max a b in 57 | (id, (max' a a', max' r r')) 58 | -------------------------------------------------------------------------------- /src/immutable/I_PNCounter.mli: -------------------------------------------------------------------------------- 1 | (** Increment / decrement counters. 2 | 3 | Contains two separate instances of {!module:I_IntVector}, one for 4 | incrementing ([add_c]) and the other for decrementing ([remove_c]). 5 | 6 | The only difference between [PNCounter] and [GCounter] is that 7 | {!val:Immutable_types.IVector.query} [t] in the former returns the difference 8 | between the [add_c] and the [remove_c] vectors. *) 9 | 10 | (** An Increment / decrement counter is a {!module:Immtable_types.IVector} 11 | with type [elt = int]*) 12 | include Immutable_types.DCounter with type elt = int 13 | -------------------------------------------------------------------------------- /src/immutable/I_USet.ml: -------------------------------------------------------------------------------- 1 | open Immutable_types 2 | 3 | (*$inject 4 | module StrUSet = I_USet.Make(struct type t = string let compare = compare end) 5 | 6 | let small t = List.length (StrUSet.value t) 7 | 8 | let print t = 9 | let v = StrUSet.value t in 10 | if List.length v = 0 then "empty_uset" 11 | else String.concat " " v 12 | 13 | let gen : StrUSet.t QCheck.Gen.t = fun r -> StrUSet.make () 14 | let uset : StrUSet.t QCheck.arbitrary = QCheck.make ~small ~print gen 15 | *) 16 | 17 | module Make (O : Comparable) = struct (*$< StrUSet *) 18 | module ISet = Set.Make (O) 19 | 20 | type t = (ISet.t * ISet.t) 21 | type elt = O.t 22 | 23 | let make () = let d = ISet.empty in (d, d) 24 | 25 | let value (a, r) = ISet.diff a r 26 | |> ISet.elements 27 | 28 | (*$QR add 29 | (* Adds monotonically advance upwards *) 30 | Q.(pair string uset) (fun (s, a) -> 31 | value a <= value (add s a) 32 | ) 33 | *) 34 | let add el (a, r) = (ISet.add el a, r) 35 | 36 | (*$QR lookup 37 | (* Lookup of s in add s always returns true *) 38 | Q.(pair string uset) (fun (s, a) -> 39 | lookup s (add s a) = true 40 | ) 41 | *) 42 | let lookup el (a, r) = ISet.diff a r 43 | |> ISet.mem el 44 | 45 | (*$QR remove 46 | (* Removes monotonically advance downwards *) 47 | Q.(pair string uset) (fun (s, a) -> 48 | value (add s a) >= value (remove s a) 49 | ) 50 | *) 51 | let remove el s = 52 | if lookup el s then begin 53 | let (a, r) = s in 54 | (a, ISet.add el r) 55 | end else s 56 | 57 | (*$QR merge 58 | Q.(triple uset uset uset) (fun (a, b, c) -> 59 | (merge a b |> value) = (merge b a |> value) && 60 | (merge a a |> value) = (value a) && 61 | (merge a (merge b c) |> value) = (merge (merge a b) c |> value)) 62 | *) 63 | let merge (a, r) (a', r') = 64 | (ISet.union a a', ISet.union r r') 65 | 66 | end (*$>*) 67 | -------------------------------------------------------------------------------- /src/immutable/I_USet.mli: -------------------------------------------------------------------------------- 1 | (** Add-once and remove-once set. 2 | 3 | {b Note}: Removed elements can never be added again. This is because of how 4 | [USet] handles the [value] operation (see below). 5 | 6 | Supports [add], [remove], [lookup] and [merge] operations. 7 | See {!module:Immutable_types.RSet}. Contains two separate instances of 8 | a regular [Map], one for adding ([add_s]) and the other for removing 9 | ([remove_s]). 10 | 11 | [add el t] adds [el] to [add_s]. 12 | 13 | [remove el t] adds [el] to [remove_s] 14 | 15 | Both [lookup] and [value] operate on the set difference [add_s \ remove_s]. 16 | 17 | [merge a b] calls merges [add_s_a] with [add_s_b] and the same for [b] *) 18 | 19 | (** Creates an add / remove set of elements satisfying 20 | {!module:Immutable_types.Comparable}*) 21 | module Make (O : Immutable_types.Comparable) : Immutable_types.RSet with 22 | type elt = O.t 23 | -------------------------------------------------------------------------------- /src/immutable/META: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: c55bd946c499bc8b9b49211314a91c62) 3 | version = "0.10.0" 4 | description = "CRDTs - OCaml style" 5 | requires = "crdt_util" 6 | archive(byte) = "crdt_immutable.cma" 7 | archive(byte, plugin) = "crdt_immutable.cma" 8 | archive(native) = "crdt_immutable.cmxa" 9 | archive(native, plugin) = "crdt_immutable.cmxs" 10 | exists_if = "crdt_immutable.cma" 11 | # OASIS_STOP 12 | 13 | -------------------------------------------------------------------------------- /src/immutable/crdt_immutable.mldylib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: c59c501b653f227262392c1eb33bf2ff) 3 | I_IntVector 4 | I_GCounter 5 | I_PNCounter 6 | I_GSet 7 | I_ORSet 8 | I_USet 9 | Immutable_types 10 | # OASIS_STOP 11 | -------------------------------------------------------------------------------- /src/immutable/crdt_immutable.mllib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: c59c501b653f227262392c1eb33bf2ff) 3 | I_IntVector 4 | I_GCounter 5 | I_PNCounter 6 | I_GSet 7 | I_ORSet 8 | I_USet 9 | Immutable_types 10 | # OASIS_STOP 11 | -------------------------------------------------------------------------------- /src/immutable/immutable_types.ml: -------------------------------------------------------------------------------- 1 | (** This module contains all immutable CRDT types, as well as some type 2 | properties that CRDT state must satisfy. *) 3 | 4 | 5 | (** Comparable types. All elements in a set must satisfy this property. 6 | 7 | Same as the built-in [Set.OrderedType], this type includes a [t] and a 8 | [compare : t -> t -> int] function. See [Pervasives.compare] *) 9 | module type Comparable = sig 10 | include Set.OrderedType 11 | end 12 | 13 | 14 | (** Mergeable types. All CRDTs satisfy this property. *) 15 | module type Mergeable = sig 16 | 17 | (** Type of mergeable elements. *) 18 | type t 19 | 20 | (** Create a new mergeable element. *) 21 | val make : unit -> t 22 | 23 | (** [merge a b] will merge the state of [a] and the one from [b] to create 24 | a new mergeable element. *) 25 | val merge : t -> t -> t 26 | end 27 | 28 | 29 | (** Vector Clock and increment-only counter types. Supports merging and 30 | incrementing. The [elt] type must be supplied when including. *) 31 | module type IVector = sig 32 | include Mergeable 33 | 34 | (** Type of the contents of an [IVector] *) 35 | type elt 36 | 37 | (** [make_in_range n] creates a new [IVector] of size ranging from [0] to [n]. 38 | being [n] greater than 0 and smaller than 2^30. 39 | 40 | When merging two CRDTs of different sizes, the smaller one grows and pads 41 | the remaining space with zeros. *) 42 | val make_in_range : int -> t 43 | 44 | (** [query t] returns the raw state of [t] *) 45 | val query : t -> elt 46 | 47 | (** [incr t] increments the position associated with the [numsite] of [t]. 48 | See {!module:I_IntVector} for more information on [numsites]. *) 49 | val incr : t -> t 50 | end 51 | 52 | 53 | (** Increment / decrement counter type. Supports merging, incrementing and 54 | decrementing. 55 | 56 | The [elt] type (included from [IVector] must be supplied when including). *) 57 | module type DCounter = sig 58 | include IVector 59 | 60 | (** [decr t] decrements the position associated with the [numsite] of [t]. 61 | See {!module:I_IntVector} for more information on [numsites]. *) 62 | val decr : t -> t 63 | end 64 | 65 | 66 | (** Grow-Only set type. Supports merging, adding and lookup operations. *) 67 | module type GSet = sig 68 | include Mergeable 69 | 70 | (** Type of the contents of [GSet] *) 71 | type elt 72 | 73 | (** [add el t] adds [el] to [t]. *) 74 | val add : elt -> t -> t 75 | 76 | (** [value t] gets the raw state of [t]. *) 77 | val value : t -> elt list 78 | 79 | (** [lookup el t] returns true if [el] is in [t]. *) 80 | val lookup : elt -> t -> bool 81 | end 82 | 83 | 84 | (** Add and remove set type. Supports merging, adding and lookup operations. *) 85 | module type RSet = sig 86 | include GSet 87 | 88 | (** [remove el t] removes [el] from [t] only if [el] is in [t]. 89 | Returns [t] otherwise. *) 90 | val remove : elt -> t -> t 91 | end 92 | -------------------------------------------------------------------------------- /src/mutable/META: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: e0debd1c5c34e0986f9c8c427e3ef37e) 3 | version = "0.10.0" 4 | description = "CRDTs - OCaml style" 5 | requires = "crdt_util" 6 | archive(byte) = "crdt_mutable.cma" 7 | archive(byte, plugin) = "crdt_mutable.cma" 8 | archive(native) = "crdt_mutable.cmxa" 9 | archive(native, plugin) = "crdt_mutable.cmxs" 10 | exists_if = "crdt_mutable.cma" 11 | # OASIS_STOP 12 | 13 | -------------------------------------------------------------------------------- /src/mutable/M_GCounter.ml: -------------------------------------------------------------------------------- 1 | open Mutable_types 2 | 3 | type elt = int 4 | type t = (elt * int list) ref 5 | 6 | let make_in_range modulo = 7 | let _ = Random.self_init () in 8 | let numsite = Random.int modulo in 9 | ref (numsite, Array.(make (numsite + 1) 0 |> to_list)) 10 | 11 | let make () = make_in_range 11 12 | 13 | let query v = List.fold_left (+) 0 (snd !v) 14 | 15 | let incr v = 16 | let id = fst !v in 17 | v := (id, IList.incr_nth (snd !v) id) 18 | 19 | let merge v v' = 20 | let (id, state) = !v and 21 | (_, state') = !v' 22 | in 23 | v := (id, IList.fill_map2 max state state') 24 | -------------------------------------------------------------------------------- /src/mutable/M_GCounter.mli: -------------------------------------------------------------------------------- 1 | (** Increment-only counters. 2 | 3 | Conceptually the same as a {!module:M_IntVector}. The only difference is 4 | that {!val:Mutable_types.IVector.query} [t] returns the sum of all the 5 | elements in the vector. *) 6 | 7 | (** An Increment-only counter is a {!module:Mutable_types.IVector} with type 8 | [elt = int]*) 9 | include Mutable_types.IVector with type elt = int 10 | -------------------------------------------------------------------------------- /src/mutable/M_GSet.ml: -------------------------------------------------------------------------------- 1 | open Mutable_types 2 | 3 | module Make (O : Comparable) = struct 4 | module ISet = Set.Make (O) 5 | 6 | type t = ISet.t ref 7 | type elt = O.t 8 | 9 | let make () = ref ISet.empty 10 | 11 | let value s = ISet.elements !s 12 | 13 | let add el s = s := ISet.add el !s 14 | 15 | let lookup el s = ISet.mem el !s 16 | 17 | let merge s s' = s := ISet.union !s !s' 18 | end 19 | -------------------------------------------------------------------------------- /src/mutable/M_GSet.mli: -------------------------------------------------------------------------------- 1 | (** Grow-Only sets. 2 | 3 | Supports [add], [lookup] and [merge] operations. 4 | See {!module:Mutable_types.GSet} *) 5 | 6 | 7 | (** Creates an grow-only set of elements satisfying 8 | {!module:Mutable_types.Comparable}*) 9 | module Make (O : Mutable_types.Comparable) : Mutable_types.GSet with 10 | type elt = O.t 11 | -------------------------------------------------------------------------------- /src/mutable/M_IntVector.ml: -------------------------------------------------------------------------------- 1 | type id = int 2 | type elt = int list 3 | type t = (id * elt) ref 4 | 5 | let make_in_range modulo = 6 | let _ = Random.self_init () in 7 | let numsite = Random.int modulo in 8 | ref (numsite, Array.(make (numsite + 1) 0 |> to_list)) 9 | 10 | let make () = make_in_range 11 11 | 12 | let query v = (snd !v) 13 | 14 | let incr t = 15 | let id = fst !t in 16 | t := (id, IList.incr_nth (snd !t) id) 17 | 18 | let merge v v' = 19 | let (id, state) = !v and 20 | (_, state') = !v' 21 | in 22 | v := (id, IList.fill_map2 max state state') 23 | -------------------------------------------------------------------------------- /src/mutable/M_IntVector.mli: -------------------------------------------------------------------------------- 1 | (** Vector Clocks. 2 | 3 | An integer vector where each replica is restricted to incrementing its own 4 | index [i]. This index is generated at random and assigned to a [numsite] 5 | value when calling [make ()] or [make_in_range n]. All subsequent calls to 6 | update operations will only act on the position noted by [numsite]. 7 | 8 | By default, {!val:Mutable_types.Mergeable.make} just calls 9 | {!val:Mutable_types.IVector.make_in_range} [n] with [n = 11]. You can 10 | override this by calling [make_in_range] directly. *) 11 | 12 | (** A Vector Clock is a {!module:Mutable_types.IVector} with type 13 | [elt = int list]*) 14 | include Mutable_types.IVector with type elt = int list 15 | 16 | -------------------------------------------------------------------------------- /src/mutable/M_ORSet.ml: -------------------------------------------------------------------------------- 1 | open Mutable_types 2 | 3 | module Make (O : Comparable) = struct 4 | module ISet = Set.Make (struct 5 | type t = (int * O.t) 6 | let compare (a, b) (c, d) = let tmp = compare a c in 7 | if tmp <> 0 then tmp else O.compare b d 8 | end) 9 | 10 | let _ = Random.self_init () 11 | 12 | type t = (ISet.t * ISet.t) ref 13 | type elt = O.t 14 | 15 | let unique () = Random.bits () 16 | 17 | let make () = let d = ISet.empty in ref (d, d) 18 | 19 | let add el s = 20 | let (a, r) = !s in 21 | s := (ISet.add (unique (), el) a, r) 22 | 23 | let value s = 24 | let (a, r) = !s in 25 | ISet.diff a r |> ISet.elements 26 | |> List.map snd 27 | |> List.sort_uniq O.compare 28 | 29 | let lookup el s = 30 | let (a, r) = !s in 31 | ISet.diff a r 32 | |> ISet.exists (fun (_, el') -> el = el') 33 | 34 | let remove el s = 35 | if lookup el s then begin 36 | let (a, r) = !s in 37 | let in_a = ISet.filter (fun (_, el') -> el = el') a 38 | in 39 | s := (a, ISet.union in_a r) 40 | end 41 | 42 | let merge s s' = 43 | let (a, r) = !s and 44 | (a', r') = !s' 45 | in 46 | s := (ISet.union a a', ISet.union r r') 47 | end 48 | -------------------------------------------------------------------------------- /src/mutable/M_ORSet.mli: -------------------------------------------------------------------------------- 1 | (** Observed-Remove set. 2 | 3 | Supports [add], [remove], [lookup] and [merge] operations. 4 | See {!module:Mutable_types.RSet}. Contains two separate instances of 5 | a regular [Map], one for adding ([add_s]) and the other for removing 6 | ([remove_s]). 7 | 8 | [add el t] adds [(unique (), el)] to [add_s], where unique is the result of 9 | calling 10 | {{:http://caml.inria.fr/pub/docs/manual-ocaml/libref/Random.html#VALbits} 11 | Random.bits}. This may or may not be enough entropy for your use case. 12 | 13 | [remove el t] adds all [{(u, el) | ∃ u : (u, el) ∈ add_s}] to [remove_s] 14 | 15 | Both [lookup] and [value] operate on the set difference [add_s \ remove_s]. 16 | 17 | [merge a b] calls merges [add_s_a] with [add_s_b] and the same for [b] *) 18 | 19 | (** Creates an add / remove set of elements satisfying 20 | {!modtype:Mutable_types.Comparable}*) 21 | module Make (O : Mutable_types.Comparable) : Mutable_types.RSet with 22 | type elt = O.t 23 | -------------------------------------------------------------------------------- /src/mutable/M_PNCounter.ml: -------------------------------------------------------------------------------- 1 | type elt = int 2 | type payload = (int list * int list) 3 | type t = (elt * payload) ref 4 | 5 | let make_in_range modulo = 6 | let _ = Random.self_init () in 7 | let numsite = Random.int modulo in 8 | let payload = Array.(make (numsite + 1) 0 |> to_list) in 9 | ref (numsite, (payload, payload)) 10 | 11 | let make () = make_in_range 11 12 | 13 | let query v = 14 | let (a, r) = snd !v in 15 | IList.fill_fold_left2 (fun acc a r -> acc + (a - r)) 0 a r 16 | 17 | let incr v = 18 | let (id, pl) = !v in 19 | let (a, r) = pl in 20 | v := (id, (IList.incr_nth a id, r)) 21 | 22 | let decr v = 23 | let (id, pl) = !v in 24 | let (a, r) = pl in 25 | v := (id, (a, IList.incr_nth r id)) 26 | 27 | let merge v v' = 28 | let (id, pl) = !v and 29 | (_, pl') = !v' 30 | in 31 | let (a, r) = pl and 32 | (a', r') = pl' and 33 | max' a b = IList.fill_map2 max a b 34 | in 35 | v := (id, (max' a a', max' r r')) 36 | -------------------------------------------------------------------------------- /src/mutable/M_PNCounter.mli: -------------------------------------------------------------------------------- 1 | (** Increment / decrement counters. 2 | 3 | Contains two separate instances of {!module:M_IntVector}, one for 4 | incrementing ([add_c]) and the other for decrementing ([remove_c]). 5 | 6 | The only difference between [PNCounter] and [GCounter] is that 7 | {!val:Mutable_types.IVector.query} [t] in the former returns the difference 8 | between the [add_c] and the [remove_c] vectors. *) 9 | 10 | (** An Increment / decrement counter is a {!module:Mutable_types.IVector} 11 | with type [elt = int]*) 12 | include Mutable_types.DCounter with type elt = int 13 | -------------------------------------------------------------------------------- /src/mutable/M_USet.ml: -------------------------------------------------------------------------------- 1 | open Mutable_types 2 | 3 | module Make (O : Comparable) = struct 4 | module ISet = Set.Make (O) 5 | 6 | type t = (ISet.t * ISet.t) ref 7 | type elt = O.t 8 | 9 | let make () = let d = ISet.empty in ref (d, d) 10 | 11 | let value s = 12 | let (a, r) = !s in 13 | ISet.elements @@ ISet.diff a r 14 | 15 | let add el s = 16 | let (a, r) = !s in 17 | s := (ISet.add el a, r) 18 | 19 | let lookup el s = 20 | let (a, r) = !s in 21 | ISet.mem el @@ ISet.diff a r 22 | 23 | let remove el s = 24 | if lookup el s then begin 25 | let (a, r) = !s in 26 | s := (a, ISet.add el r) 27 | end 28 | 29 | let merge s s' = 30 | let (a, r) = !s and 31 | (a', r') = !s' 32 | in 33 | s := (ISet.union a a', ISet.union r r') 34 | 35 | end 36 | -------------------------------------------------------------------------------- /src/mutable/M_USet.mli: -------------------------------------------------------------------------------- 1 | (** Add-once and remove-once set. 2 | 3 | {b Note}: Removed elements can never be added again. This is because of how 4 | [USet] handles the [value] operation (see below). 5 | 6 | Supports [add], [remove], [lookup] and [merge] operations. 7 | See {!module:Mutable_types.RSet}. Contains two separate instances of 8 | a regular [Map], one for adding ([add_s]) and the other for removing 9 | ([remove_s]). 10 | 11 | [add el t] adds [el] to [add_s]. 12 | 13 | [remove el t] adds [el] to [remove_s] 14 | 15 | Both [lookup] and [value] operate on the set difference [add_s \ remove_s]. 16 | 17 | [merge a b] calls merges [add_s_a] with [add_s_b] and the same for [b] *) 18 | 19 | (** Creates an add / remove set of elements satisfying 20 | {!module:Mutable_types.Comparable}*) 21 | module Make (O : Mutable_types.Comparable) : Mutable_types.RSet with 22 | type elt = O.t 23 | -------------------------------------------------------------------------------- /src/mutable/crdt_mutable.mldylib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: e7c43c393f98739b71ed6c1c766ea1b5) 3 | M_GCounter 4 | M_GSet 5 | M_IntVector 6 | M_ORSet 7 | M_PNCounter 8 | M_USet 9 | Mutable_types 10 | # OASIS_STOP 11 | -------------------------------------------------------------------------------- /src/mutable/crdt_mutable.mllib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: e7c43c393f98739b71ed6c1c766ea1b5) 3 | M_GCounter 4 | M_GSet 5 | M_IntVector 6 | M_ORSet 7 | M_PNCounter 8 | M_USet 9 | Mutable_types 10 | # OASIS_STOP 11 | -------------------------------------------------------------------------------- /src/mutable/mutable_types.ml: -------------------------------------------------------------------------------- 1 | (** This module contains all mutable CRDT types, as well as some type 2 | properties that CRDT state must satisfy. *) 3 | 4 | 5 | (** Comparable types. All elements in a set must satisfy this property. 6 | 7 | Same as the built-in [Set.OrderedType], this type includes a [t] and a 8 | [compare : t -> t -> int] function. See [Pervasives.compare] *) 9 | module type Comparable = sig 10 | include Set.OrderedType 11 | end 12 | 13 | 14 | (** Mergeable types. All CRDTs satisfy this property. *) 15 | module type Mergeable = sig 16 | 17 | (** Type of mergeable elements. *) 18 | type t 19 | 20 | (** Create a new mergeable element. *) 21 | val make : unit -> t 22 | 23 | (** [merge a b] will merge the state of [b] with the one from [a]. 24 | Updates [a]. *) 25 | val merge : t -> t -> unit 26 | end 27 | 28 | 29 | (** Vector Clock and increment-only counter types. Supports merging and 30 | incrementing. The [elt] type must be supplied when including. *) 31 | module type IVector = sig 32 | include Mergeable 33 | 34 | (** Type of the contents of an [IVector] *) 35 | type elt 36 | 37 | (** [make_in_range n] creates a new [IVector] of size ranging from [0] to [n]. 38 | being [n] greater than 0 and smaller than 2^30. 39 | 40 | When merging two CRDTs of different sizes, the smaller one grows and pads 41 | the remaining space with zeros. *) 42 | val make_in_range : int -> t 43 | 44 | (** [query t] returns the raw state of [t] *) 45 | val query : t -> elt 46 | 47 | (** [incr t] increments the position associated with the [numsite] of [t]. 48 | See {!module:M_IntVector} for more information on [numsites]. *) 49 | val incr : t -> unit 50 | end 51 | 52 | 53 | (** Increment / decrement counter type. Supports merging, incrementing and 54 | decrementing. 55 | 56 | The [elt] type (included from [IVector] must be supplied when including). *) 57 | module type DCounter = sig 58 | include IVector 59 | 60 | (** [decr t] decrements the position associated with the [numsite] of [t]. 61 | See {!module:M_IntVector} for more information on [numsites]. *) 62 | val decr : t -> unit 63 | end 64 | 65 | 66 | (** Grow-Only set type. Supports merging, adding and lookup operations. *) 67 | module type GSet = sig 68 | include Mergeable 69 | 70 | (** Type of the contents of [GSet] *) 71 | type elt 72 | 73 | (** [add el t] adds [el] in-place to [t]. *) 74 | val add : elt -> t -> unit 75 | 76 | (** [value t] gets the raw state of [t]. *) 77 | val value : t -> elt list 78 | 79 | (** [lookup el t] returns true if [el] is in [t]. *) 80 | val lookup : elt -> t -> bool 81 | end 82 | 83 | 84 | (** Add and remove set type. Supports merging, adding and lookup operations. *) 85 | module type RSet = sig 86 | include GSet 87 | 88 | (** [remove el t] removes [el] from [t] only if [el] is in [t]. 89 | Does nothing otherwise. *) 90 | val remove : elt -> t -> unit 91 | end 92 | -------------------------------------------------------------------------------- /src/util/IList.ml: -------------------------------------------------------------------------------- 1 | open List 2 | 3 | let incr_nth: int list -> int -> int list = fun l pos -> 4 | List.mapi 5 | (fun ith el -> 6 | if ith = pos then el + 1 else el) 7 | l 8 | 9 | let rec fillz : int list -> int -> int list = fun l n -> 10 | if n = 0 then l 11 | else fillz (l @ [0]) (n - 1) 12 | 13 | let fill_map2 f l l' = 14 | let la = List.length l and 15 | lb = List.length l' in 16 | let diff = abs @@ la - lb in 17 | if la = lb then List.map2 f l l' 18 | else if la > lb then List.map2 f l @@ fillz l' diff 19 | else List.map2 f (fillz l diff) l' 20 | 21 | let fill_fold_left2 f acc l l' = 22 | let la = List.length l and 23 | lb = List.length l' in 24 | let diff = abs @@ la - lb in 25 | if la = lb then List.fold_left2 f acc l l' 26 | else if la > lb then List.fold_left2 f acc l @@ fillz l' diff 27 | else List.fold_left2 f acc (fillz l diff) l' 28 | -------------------------------------------------------------------------------- /src/util/IList.mli: -------------------------------------------------------------------------------- 1 | (** Helper List library that supports dynamic padding for higher-order 2 | functions operating on lists of different length. *) 3 | 4 | open List 5 | 6 | (** [incr_nth l n] adds one to the [n]th element of l. *) 7 | val incr_nth: int list -> int -> int list 8 | 9 | (** [fill_map2 f l l'] padds with zeros the smaller list before applying [f]. *) 10 | val fill_map2 : (int -> int -> int) -> int list -> int list -> int list 11 | 12 | (** [fill_fold_left2 f l l'] padds with zeros the smaller list before applying [f]. *) 13 | val fill_fold_left2 : (int -> int -> int -> int) -> int -> int list -> int list -> int 14 | -------------------------------------------------------------------------------- /src/util/META: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: 6c8f51034166f15cf365746143132df7) 3 | version = "0.10.0" 4 | description = "CRDTs - OCaml style" 5 | archive(byte) = "crdt_util.cma" 6 | archive(byte, plugin) = "crdt_util.cma" 7 | archive(native) = "crdt_util.cmxa" 8 | archive(native, plugin) = "crdt_util.cmxs" 9 | exists_if = "crdt_util.cma" 10 | # OASIS_STOP 11 | 12 | -------------------------------------------------------------------------------- /src/util/crdt_util.mldylib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: ad7cce600f0e290b37b99b9d8c11529b) 3 | IList 4 | # OASIS_STOP 5 | -------------------------------------------------------------------------------- /src/util/crdt_util.mllib: -------------------------------------------------------------------------------- 1 | # OASIS_START 2 | # DO NOT EDIT (digest: ad7cce600f0e290b37b99b9d8c11529b) 3 | IList 4 | # OASIS_STOP 5 | -------------------------------------------------------------------------------- /test/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ergl/crdt-ml/44e474a2346a3b3af8c30fe5f0ce96ae4024fdae/test/.gitkeep --------------------------------------------------------------------------------