ic-mops 0.8.3 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/.mops/base@0.7.4/LICENSE +208 -0
  2. package/.mops/base@0.7.4/README.md +64 -0
  3. package/.mops/base@0.7.4/mops.toml +5 -0
  4. package/.mops/base@0.7.4/src/Array.mo +686 -0
  5. package/.mops/base@0.7.4/src/AssocList.mo +203 -0
  6. package/.mops/base@0.7.4/src/Blob.mo +55 -0
  7. package/.mops/base@0.7.4/src/Bool.mo +44 -0
  8. package/.mops/base@0.7.4/src/Buffer.mo +1937 -0
  9. package/.mops/base@0.7.4/src/CertifiedData.mo +29 -0
  10. package/.mops/base@0.7.4/src/Char.mo +67 -0
  11. package/.mops/base@0.7.4/src/Debug.mo +15 -0
  12. package/.mops/base@0.7.4/src/Deque.mo +75 -0
  13. package/.mops/base@0.7.4/src/Error.mo +41 -0
  14. package/.mops/base@0.7.4/src/ExperimentalCycles.mo +51 -0
  15. package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +36 -0
  16. package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +121 -0
  17. package/.mops/base@0.7.4/src/Float.mo +150 -0
  18. package/.mops/base@0.7.4/src/Func.mo +38 -0
  19. package/.mops/base@0.7.4/src/Hash.mo +83 -0
  20. package/.mops/base@0.7.4/src/HashMap.mo +229 -0
  21. package/.mops/base@0.7.4/src/Heap.mo +113 -0
  22. package/.mops/base@0.7.4/src/Int.mo +150 -0
  23. package/.mops/base@0.7.4/src/Int16.mo +159 -0
  24. package/.mops/base@0.7.4/src/Int32.mo +160 -0
  25. package/.mops/base@0.7.4/src/Int64.mo +161 -0
  26. package/.mops/base@0.7.4/src/Int8.mo +160 -0
  27. package/.mops/base@0.7.4/src/Iter.mo +220 -0
  28. package/.mops/base@0.7.4/src/IterType.mo +7 -0
  29. package/.mops/base@0.7.4/src/List.mo +433 -0
  30. package/.mops/base@0.7.4/src/Nat.mo +75 -0
  31. package/.mops/base@0.7.4/src/Nat16.mo +146 -0
  32. package/.mops/base@0.7.4/src/Nat32.mo +146 -0
  33. package/.mops/base@0.7.4/src/Nat64.mo +146 -0
  34. package/.mops/base@0.7.4/src/Nat8.mo +146 -0
  35. package/.mops/base@0.7.4/src/None.mo +19 -0
  36. package/.mops/base@0.7.4/src/Option.mo +160 -0
  37. package/.mops/base@0.7.4/src/Order.mo +46 -0
  38. package/.mops/base@0.7.4/src/Prelude.mo +33 -0
  39. package/.mops/base@0.7.4/src/Principal.mo +58 -0
  40. package/.mops/base@0.7.4/src/RBTree.mo +218 -0
  41. package/.mops/base@0.7.4/src/Random.mo +188 -0
  42. package/.mops/base@0.7.4/src/Result.mo +210 -0
  43. package/.mops/base@0.7.4/src/Stack.mo +40 -0
  44. package/.mops/base@0.7.4/src/Text.mo +615 -0
  45. package/.mops/base@0.7.4/src/Time.mo +37 -0
  46. package/.mops/base@0.7.4/src/Trie.mo +1200 -0
  47. package/.mops/base@0.7.4/src/TrieMap.mo +180 -0
  48. package/.mops/base@0.7.4/src/TrieSet.mo +97 -0
  49. package/.mops/base@0.8.3/LICENSE +208 -0
  50. package/.mops/base@0.8.3/README.md +64 -0
  51. package/.mops/base@0.8.3/mops.toml +6 -0
  52. package/.mops/base@0.8.3/src/Array.mo +717 -0
  53. package/.mops/base@0.8.3/src/AssocList.mo +404 -0
  54. package/.mops/base@0.8.3/src/Blob.mo +212 -0
  55. package/.mops/base@0.8.3/src/Bool.mo +44 -0
  56. package/.mops/base@0.8.3/src/Buffer.mo +2660 -0
  57. package/.mops/base@0.8.3/src/CertifiedData.mo +53 -0
  58. package/.mops/base@0.8.3/src/Char.mo +65 -0
  59. package/.mops/base@0.8.3/src/Debug.mo +56 -0
  60. package/.mops/base@0.8.3/src/Deque.mo +243 -0
  61. package/.mops/base@0.8.3/src/Error.mo +68 -0
  62. package/.mops/base@0.8.3/src/ExperimentalCycles.mo +151 -0
  63. package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +60 -0
  64. package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +348 -0
  65. package/.mops/base@0.8.3/src/Float.mo +843 -0
  66. package/.mops/base@0.8.3/src/Func.mo +46 -0
  67. package/.mops/base@0.8.3/src/Hash.mo +82 -0
  68. package/.mops/base@0.8.3/src/HashMap.mo +457 -0
  69. package/.mops/base@0.8.3/src/Heap.mo +233 -0
  70. package/.mops/base@0.8.3/src/Int.mo +365 -0
  71. package/.mops/base@0.8.3/src/Int16.mo +521 -0
  72. package/.mops/base@0.8.3/src/Int32.mo +522 -0
  73. package/.mops/base@0.8.3/src/Int64.mo +522 -0
  74. package/.mops/base@0.8.3/src/Int8.mo +522 -0
  75. package/.mops/base@0.8.3/src/Iter.mo +227 -0
  76. package/.mops/base@0.8.3/src/IterType.mo +7 -0
  77. package/.mops/base@0.8.3/src/List.mo +930 -0
  78. package/.mops/base@0.8.3/src/Nat.mo +305 -0
  79. package/.mops/base@0.8.3/src/Nat16.mo +144 -0
  80. package/.mops/base@0.8.3/src/Nat32.mo +144 -0
  81. package/.mops/base@0.8.3/src/Nat64.mo +144 -0
  82. package/.mops/base@0.8.3/src/Nat8.mo +144 -0
  83. package/.mops/base@0.8.3/src/None.mo +19 -0
  84. package/.mops/base@0.8.3/src/Option.mo +154 -0
  85. package/.mops/base@0.8.3/src/Order.mo +46 -0
  86. package/.mops/base@0.8.3/src/Prelude.mo +33 -0
  87. package/.mops/base@0.8.3/src/Principal.mo +249 -0
  88. package/.mops/base@0.8.3/src/RBTree.mo +681 -0
  89. package/.mops/base@0.8.3/src/Random.mo +270 -0
  90. package/.mops/base@0.8.3/src/Result.mo +209 -0
  91. package/.mops/base@0.8.3/src/Stack.mo +93 -0
  92. package/.mops/base@0.8.3/src/Text.mo +761 -0
  93. package/.mops/base@0.8.3/src/Time.mo +36 -0
  94. package/.mops/base@0.8.3/src/Timer.mo +62 -0
  95. package/.mops/base@0.8.3/src/Trie.mo +1603 -0
  96. package/.mops/base@0.8.3/src/TrieMap.mo +392 -0
  97. package/.mops/base@0.8.3/src/TrieSet.mo +148 -0
  98. package/mops.js +1 -1
  99. package/network.txt +1 -0
  100. package/package.json +2 -2
@@ -0,0 +1,160 @@
1
+ /// Typesafe nulls
2
+ ///
3
+ /// Optional values can be seen as a typesafe `null`. A value of type `?Int` can
4
+ /// be constructed with either `null` or `?42`. The simplest way to get at the
5
+ /// contents of an optional is to use pattern matching:
6
+ ///
7
+ /// ```motoko
8
+ /// let optionalInt1 : ?Int = ?42;
9
+ /// let optionalInt2 : ?Int = null;
10
+ ///
11
+ /// let int1orZero : Int = switch optionalInt1 {
12
+ /// case null 0;
13
+ /// case (?int) int;
14
+ /// };
15
+ /// assert int1orZero == 42;
16
+ ///
17
+ /// let int2orZero : Int = switch optionalInt2 {
18
+ /// case null 0;
19
+ /// case (?int) int;
20
+ /// };
21
+ /// assert int2orZero == 0;
22
+ /// ```
23
+ ///
24
+ /// The functions in this module capture some common operations when working
25
+ /// with optionals that can be more succinct than using pattern matching.
26
+
27
+ import P "Prelude";
28
+
29
+ module {
30
+
31
+ /// Unwraps an optional value, with a default value, i.e. `get(?x, d) = x` and
32
+ /// `get(null, d) = d`.
33
+ public func get<T>(x : ?T, default : T) : T =
34
+ switch x {
35
+ case null { default };
36
+ case (?x_) { x_ };
37
+ };
38
+
39
+ /// Unwraps an optional value using a function, or returns the default, i.e.
40
+ /// `option(?x, f, d) = f x` and `option(null, f, d) = d`.
41
+ public func getMapped<A, B>(x : ?A, f : A -> B, default : B) : B =
42
+ switch x {
43
+ case null { default };
44
+ case (?x_) { f(x_) };
45
+ };
46
+
47
+ /// Applies a function to the wrapped value. `null`'s are left untouched.
48
+ /// ```motoko
49
+ /// import Option "mo:base/Option";
50
+ /// assert Option.map<Nat, Nat>(?42, func x = x + 1) == ?43;
51
+ /// assert Option.map<Nat, Nat>(null, func x = x + 1) == null;
52
+ /// ```
53
+ public func map<A, B>(x : ?A, f : A -> B) : ?B =
54
+ switch x {
55
+ case null { null };
56
+ case (?x_) { ?f(x_) };
57
+ };
58
+
59
+ /// Applies a function to the wrapped value, but discards the result. Use
60
+ /// `iterate` if you're only interested in the side effect `f` produces.
61
+ ///
62
+ /// ```motoko
63
+ /// import Option "mo:base/Option";
64
+ /// var counter : Nat = 0;
65
+ /// Option.iterate(?5, func (x : Nat) { counter += x });
66
+ /// assert counter == 5;
67
+ /// Option.iterate(null, func (x : Nat) { counter += x });
68
+ /// assert counter == 5;
69
+ /// ```
70
+ public func iterate<A>(x : ?A, f : A -> ()) =
71
+ switch x {
72
+ case null {};
73
+ case (?x_) { f(x_) };
74
+ };
75
+
76
+ /// Applies an optional function to an optional value. Returns `null` if at
77
+ /// least one of the arguments is `null`.
78
+ public func apply<A, B>(x : ?A, f : ?(A -> B)) : ?B {
79
+ switch (f, x) {
80
+ case (?f_, ?x_) {
81
+ ?f_(x_);
82
+ };
83
+ case (_, _) {
84
+ null;
85
+ };
86
+ };
87
+ };
88
+
89
+ /// Applies a function to an optional value. Returns `null` if the argument is
90
+ /// `null`, or the function returns `null`.
91
+ public func chain<A, B>(x : ?A, f : A -> ?B) : ?B {
92
+ switch(x) {
93
+ case (?x_) {
94
+ f(x_);
95
+ };
96
+ case (null) {
97
+ null;
98
+ };
99
+ };
100
+ };
101
+
102
+ /// Given an optional optional value, removes one layer of optionality.
103
+ /// ```motoko
104
+ /// import Option "mo:base/Option";
105
+ /// assert Option.flatten(?(?(42))) == ?42;
106
+ /// assert Option.flatten(?(null)) == null;
107
+ /// assert Option.flatten(null) == null;
108
+ /// ```
109
+ public func flatten<A>(x : ??A) : ?A {
110
+ chain<?A, A>(x, func (x_ : ?A) : ?A {
111
+ x_;
112
+ });
113
+ };
114
+
115
+ /// Creates an optional value from a definite value.
116
+ /// ```motoko
117
+ /// import Option "mo:base/Option";
118
+ /// assert Option.make(42) == ?42;
119
+ /// ```
120
+ public func make<A>(x: A) : ?A = ?x;
121
+
122
+ /// Returns true if the argument is not `null`, otherwise returns false.
123
+ public func isSome(x : ?Any) : Bool =
124
+ switch x {
125
+ case null { false };
126
+ case _ { true };
127
+ };
128
+
129
+ /// Returns true if the argument is `null`, otherwise returns false.
130
+ public func isNull(x : ?Any) : Bool =
131
+ switch x {
132
+ case null { true };
133
+ case _ { false };
134
+ };
135
+
136
+ /// Asserts that the value is not `null`; fails otherwise.
137
+ /// @deprecated Option.assertSome will be removed soon; use an assert expression instead
138
+ public func assertSome(x : ?Any) =
139
+ switch x {
140
+ case null { P.unreachable() };
141
+ case _ {};
142
+ };
143
+
144
+ /// Asserts that the value _is_ `null`; fails otherwise.
145
+ /// @deprecated Option.assertNull will be removed soon; use an assert expression instead
146
+ public func assertNull(x : ?Any) =
147
+ switch x {
148
+ case null { };
149
+ case _ { P.unreachable() };
150
+ };
151
+
152
+ /// Unwraps an optional value, i.e. `unwrap(?x) = x`.
153
+ ///
154
+ /// @deprecated Option.unwrap is unsafe and fails if the argument is null; it will be removed soon; use a `switch` or `do?` expression instead
155
+ public func unwrap<T>(x : ?T) : T =
156
+ switch x {
157
+ case null { P.unreachable() };
158
+ case (?x_) { x_ };
159
+ };
160
+ }
@@ -0,0 +1,46 @@
1
+ /// Order
2
+
3
+ module {
4
+
5
+ /// A type to represent an order.
6
+ public type Order = {
7
+ #less;
8
+ #equal;
9
+ #greater;
10
+ };
11
+
12
+ /// Check if an order is #less.
13
+ public func isLess(order : Order) : Bool {
14
+ switch order {
15
+ case (#less) { true };
16
+ case _ { false };
17
+ };
18
+ };
19
+
20
+ /// Check if an order is #equal.
21
+ public func isEqual(order : Order) : Bool {
22
+ switch order {
23
+ case (#equal) { true };
24
+ case _ { false };
25
+ };
26
+ };
27
+
28
+ /// Check if an order is #greater.
29
+ public func isGreater(order : Order) : Bool {
30
+ switch order {
31
+ case (#greater) { true };
32
+ case _ { false };
33
+ };
34
+ };
35
+
36
+ /// Returns true if only if `o1` and `o2` are the same ordering.
37
+ public func equal(o1 : Order, o2: Order) : Bool {
38
+ switch (o1, o2) {
39
+ case (#less, #less) { true };
40
+ case (#equal, #equal) { true };
41
+ case (#greater, #greater) { true };
42
+ case _ { false };
43
+ };
44
+ };
45
+
46
+ };
@@ -0,0 +1,33 @@
1
+ /// General utilities
2
+ ///
3
+ /// This prelude file proposes standard library features that _may_
4
+ /// belong in the _language_ (compiler-internal) prelude sometime, after
5
+ /// some further experience and discussion. Until then, they live here.
6
+
7
+ import Debug "Debug";
8
+
9
+ module {
10
+
11
+ /// Not yet implemented
12
+ ///
13
+ /// Mark incomplete code with the `nyi` and `xxx` functions.
14
+ ///
15
+ /// Each have calls are well-typed in all typing contexts, which
16
+ /// trap in all execution contexts.
17
+ public func nyi() : None {
18
+ Debug.trap("Prelude.nyi()");
19
+ };
20
+
21
+ public func xxx() : None {
22
+ Debug.trap("Prelude.xxx()");
23
+ };
24
+
25
+ /// Mark unreachable code with the `unreachable` function.
26
+ ///
27
+ /// Calls are well-typed in all typing contexts, and they
28
+ /// trap in all execution contexts.
29
+ public func unreachable() : None {
30
+ Debug.trap("Prelude.unreachable()")
31
+ };
32
+
33
+ }
@@ -0,0 +1,58 @@
1
+ /// IC principals (user and canister smart contract IDs)
2
+
3
+ import Prim "mo:⛔";
4
+ import Blob "Blob";
5
+ import Hash "Hash";
6
+ module {
7
+
8
+ /// Internet Computer principal identifiers.
9
+ /// Convert to `Blob` for access to bytes.
10
+ public type Principal = Prim.Types.Principal;
11
+
12
+ /// Conversion.
13
+ public let fromActor : (a : actor {}) -> Principal = Prim.principalOfActor;
14
+
15
+ /// Conversion.
16
+ public let toBlob : (p : Principal) -> Blob = Prim.blobOfPrincipal;
17
+
18
+ /// Conversion.
19
+ public let fromBlob : (b : Blob) -> Principal = Prim.principalOfBlob;
20
+
21
+ /// Conversion.
22
+ public func toText(p : Principal) : Text = debug_show(p);
23
+
24
+ private let anonymousPrincipal : Blob = "\04";
25
+
26
+ public func isAnonymous(p : Principal) : Bool =
27
+ Prim.blobOfPrincipal p == anonymousPrincipal;
28
+
29
+ public func hash(principal : Principal) : Hash.Hash =
30
+ Blob.hash (Prim.blobOfPrincipal(principal));
31
+
32
+ public func fromText(t : Text) : Principal = fromActor(actor(t));
33
+
34
+ /// Returns `x == y`.
35
+ public func equal(x : Principal, y : Principal) : Bool { x == y };
36
+
37
+ /// Returns `x != y`.
38
+ public func notEqual(x : Principal, y : Principal) : Bool { x != y };
39
+
40
+ /// Returns `x < y`.
41
+ public func less(x : Principal, y : Principal) : Bool { x < y };
42
+
43
+ /// Returns `x <= y`.
44
+ public func lessOrEqual(x : Principal, y : Principal) : Bool { x <= y };
45
+
46
+ /// Returns `x > y`.
47
+ public func greater(x : Principal, y : Principal) : Bool { x > y };
48
+
49
+ /// Returns `x >= y`.
50
+ public func greaterOrEqual(x : Principal, y : Principal) : Bool { x >= y };
51
+
52
+ /// Returns the order of `x` and `y`.
53
+ public func compare(x : Principal, y : Principal) : { #less; #equal; #greater } {
54
+ if (x < y) { #less }
55
+ else if (x == y) { #equal }
56
+ else { #greater }
57
+ };
58
+ }
@@ -0,0 +1,218 @@
1
+ /// Red-Black Trees
2
+
3
+ import Debug "Debug";
4
+ import I "Iter";
5
+ import List "List";
6
+ import Nat "Nat";
7
+ import O "Order";
8
+
9
+ module {
10
+
11
+ /// Node color: red or black.
12
+ public type Color = { #R; #B };
13
+
14
+ /// Ordered, (red-black) tree of entries.
15
+ public type Tree<X, Y> = {
16
+ #node : (Color, Tree<X, Y>, (X, ?Y), Tree<X, Y>);
17
+ #leaf;
18
+ };
19
+
20
+ /// Create an order map from an order function for its keys.
21
+ public class RBTree<X, Y>(compareTo : (X, X) -> O.Order) {
22
+
23
+ var tree : Tree<X, Y> = (#leaf : Tree<X, Y>);
24
+
25
+ /// Tree as sharable data.
26
+ ///
27
+ /// Get non-OO, purely-functional representation:
28
+ /// for drawing, pretty-printing and non-OO contexts
29
+ /// (e.g., async args and results):
30
+ public func share() : Tree<X, Y> {
31
+ tree
32
+ };
33
+
34
+ /// Get the value associated with a given key.
35
+ public func get(x : X) : ?Y {
36
+ getRec(x, compareTo, tree);
37
+ };
38
+
39
+ /// Replace the value associated with a given key.
40
+ public func replace(x : X, y : Y) : ?Y {
41
+ let (res, t) = insertRoot(x, compareTo, y, tree);
42
+ tree := t;
43
+ res
44
+ };
45
+
46
+ /// Put an entry: A value associated with a given key.
47
+ public func put(x : X, y : Y) {
48
+ let (res, t) = insertRoot(x, compareTo, y, tree);
49
+ tree := t;
50
+ };
51
+
52
+ /// Delete the entry associated with a given key.
53
+ public func delete(x : X) {
54
+ let (res, t) = removeRec(x, compareTo, tree);
55
+ tree := t
56
+ };
57
+
58
+ /// Remove the entry associated with a given key.
59
+ public func remove(x : X) : ?Y {
60
+ let (res, t) = removeRec(x, compareTo, tree);
61
+ tree := t;
62
+ res
63
+ };
64
+
65
+ /// An iterator for the key-value entries of the map, in ascending key order.
66
+ ///
67
+ /// iterator is persistent, like the tree itself
68
+ public func entries() : I.Iter<(X, Y)> { iter(tree, #fwd) };
69
+
70
+ /// An iterator for the key-value entries of the map, in descending key order.
71
+ ///
72
+ /// iterator is persistent, like the tree itself
73
+ public func entriesRev() : I.Iter<(X, Y)> { iter(tree, #bwd) };
74
+
75
+ };
76
+
77
+
78
+ type IterRep<X, Y> = List.List<{ #tr:Tree<X, Y>; #xy:(X, ?Y) }>;
79
+
80
+ /// An iterator for the entries of the map, in ascending (`#fwd`) or descending (`#bwd`) order.
81
+ public func iter<X, Y>(t : Tree<X, Y>, dir : { #fwd; #bwd }) : I.Iter<(X, Y)> {
82
+ object {
83
+ var trees : IterRep<X, Y> = ?(#tr(t), null);
84
+ public func next() : ?(X, Y) {
85
+ switch (dir, trees) {
86
+ case (_, null) { null };
87
+ case (_, ?(#tr(#leaf), ts)){
88
+ trees := ts;
89
+ next()
90
+ };
91
+ case (_, ?(#xy(xy), ts)) {
92
+ trees := ts;
93
+ switch (xy.1) {
94
+ case null { next() };
95
+ case (?y) { ?(xy.0, y) }
96
+ }
97
+ };
98
+ case (#fwd, ?(#tr(#node(_, l, xy, r)), ts)) {
99
+ trees := ?(#tr(l), ?(#xy(xy), ?(#tr(r), ts)));
100
+ next()
101
+ };
102
+ case (#bwd, ?(#tr(#node(_, l, xy, r)), ts)) {
103
+ trees := ?(#tr(r), ?(#xy(xy), ?(#tr(l), ts)));
104
+ next()
105
+ };
106
+ }
107
+ };
108
+ }
109
+ };
110
+
111
+ /// Remove the value associated with a given key.
112
+ func removeRec<X, Y>(x : X, compareTo : (X, X) -> O.Order, t : Tree<X, Y>)
113
+ : (?Y, Tree<X, Y>) {
114
+ switch t {
115
+ case (#leaf) { (null, #leaf) };
116
+ case (#node(c, l, xy, r)) {
117
+ switch (compareTo(x, xy.0)) {
118
+ case (#less) {
119
+ let (yo, l2) = removeRec(x, compareTo, l);
120
+ (yo, #node(c, l2, xy, r))
121
+ };
122
+ case (#equal) {
123
+ (xy.1, #node(c, l, (x, null), r))
124
+ };
125
+ case (#greater) {
126
+ let (yo, r2) = removeRec(x, compareTo, r);
127
+ (yo, #node(c, l, xy, r2))
128
+ };
129
+ }
130
+ }
131
+ }
132
+ };
133
+
134
+
135
+
136
+ func bal<X, Y>(color : Color, lt : Tree<X, Y>, kv : (X, ?Y), rt : Tree<X, Y>) : Tree<X, Y> {
137
+ // thank you, algebraic pattern matching!
138
+ // following notes from [Ravi Chugh](https://www.classes.cs.uchicago.edu/archive/2019/spring/22300-1/lectures/RedBlackTrees/index.html)
139
+ switch (color, lt, kv, rt) {
140
+ case (#B, #node(#R, #node(#R, a, x, b), y, c), z, d) {
141
+ #node(#R, #node(#B, a, x, b), y, #node(#B, c, z, d))
142
+ };
143
+ case (#B, #node(#R, a, x, #node(#R, b, y, c)), z, d) {
144
+ #node(#R, #node(#B, a, x, b), y, #node(#B, c, z, d))
145
+ };
146
+ case (#B, a, x, #node(#R, #node(#R, b, y, c), z, d)) {
147
+ #node(#R, #node(#B, a, x, b), y, #node(#B, c, z, d))
148
+ };
149
+ case (#B, a, x, #node(#R, b, y, #node(#R, c, z, d))) {
150
+ #node(#R, #node(#B, a, x, b), y, #node(#B, c, z, d))
151
+ };
152
+ case _ { #node(color, lt, kv, rt) };
153
+ }
154
+ };
155
+
156
+ func insertRoot<X, Y>(x : X, compareTo : (X, X) -> O.Order, y : Y, t : Tree<X, Y>)
157
+ : (?Y, Tree<X, Y>) {
158
+ switch (insertRec(x, compareTo, y, t)) {
159
+ case (_, #leaf) { assert false; loop { } };
160
+ case (yo, #node(_, l, xy, r)) { (yo, #node(#B, l, xy, r)) };
161
+ }
162
+ };
163
+
164
+ func insertRec<X, Y>(x : X, compareTo : (X, X) -> O.Order, y : Y, t : Tree<X, Y>)
165
+ : (?Y, Tree<X, Y>) {
166
+ switch t {
167
+ case (#leaf) { (null, #node(#R, #leaf, (x, ?y), #leaf)) };
168
+ case (#node(c, l, xy, r)) {
169
+ switch (compareTo(x, xy.0)) {
170
+ case (#less) {
171
+ let (yo, l2) = insertRec(x, compareTo, y, l);
172
+ (yo, bal(c, l2, xy, r))
173
+ };
174
+ case (#equal) {
175
+ (xy.1, #node(c, l, (x, ?y), r))
176
+ };
177
+ case (#greater) {
178
+ let (yo, r2) = insertRec(x, compareTo, y, r);
179
+ (yo, bal(c, l, xy, r2))
180
+ };
181
+ }
182
+ }
183
+ }
184
+ };
185
+
186
+ func getRec<X, Y>(x : X, compareTo : (X, X) -> O.Order, t : Tree<X, Y>) : ?Y {
187
+ switch t {
188
+ case (#leaf) { null };
189
+ case (#node(c, l, xy, r)) {
190
+ switch (compareTo(x, xy.0)) {
191
+ case (#less) { getRec(x, compareTo, l) };
192
+ case (#equal) { xy.1 };
193
+ case (#greater) { getRec(x, compareTo, r) };
194
+ }
195
+ };
196
+ }
197
+ };
198
+
199
+ func height<X, Y>(t : Tree<X, Y>) : Nat {
200
+ switch t {
201
+ case (#leaf) { 0 };
202
+ case (#node(_, l, _, r)) {
203
+ Nat.max(height(l), height(r)) + 1
204
+ }
205
+ }
206
+ };
207
+
208
+ /// The size of the tree as the number of key-value entries.
209
+ public func size<X, Y>(t : Tree<X, Y>) : Nat {
210
+ switch t {
211
+ case (#leaf) { 0 };
212
+ case (#node(_, l, xy, r)) {
213
+ size(l) + size(r) + (switch (xy.1) { case null 0; case _ 1 });
214
+ };
215
+ }
216
+ };
217
+
218
+ }
@@ -0,0 +1,188 @@
1
+ /// A module for obtaining randomness on the Internet Computer (IC).
2
+ ///
3
+ /// This module provides the fundamentals for user abstractions to build on.
4
+ ///
5
+ /// Dealing with randomness on a deterministic computing platform, such
6
+ /// as the IC, is intricate. Some basic rules need to be followed by the
7
+ /// user of this module to obtain (and maintain) the benefits of crypto-
8
+ /// graphic randomness:
9
+ ///
10
+ /// - cryptographic entropy (randomness source) is only obtainable
11
+ /// asyncronously in discrete chunks of 256 bits (32-byte sized `Blob`s)
12
+ /// - all bets must be closed *before* entropy is being asked for in
13
+ /// order to decide them
14
+ /// - this implies that the same entropy (i.e. `Blob`) - or surplus entropy
15
+ /// not utilised yet - cannot be used for a new round of bets without
16
+ /// losing the cryptographic guarantees.
17
+ ///
18
+ /// Concretely, the below class `Finite`, as well as the
19
+ /// `*From` methods risk the carrying-over of state from previous rounds.
20
+ /// These are provided for performance (and convenience) reasons, and need
21
+ /// special care when used. Similar caveats apply for user-defined (pseudo)
22
+ /// random number generators.
23
+
24
+ import I "Iter";
25
+ import Option "Option";
26
+ import P "Prelude";
27
+ import Prim "mo:⛔";
28
+
29
+ module {
30
+
31
+ /// Drawing from a finite supply of entropy, `Finite` provides
32
+ /// methods to obtain random values. When the entropy is used up,
33
+ /// `null` is returned. Otherwise the outcomes' distributions are
34
+ /// stated for each method. The uniformity of outcomes is
35
+ /// guaranteed only when the supplied entropy is originally obtained
36
+ /// by the `blob()` call, and is never reused.
37
+ public class Finite(entropy : Blob) {
38
+ let it : I.Iter<Nat8> = entropy.vals();
39
+
40
+ /// Uniformly distributes outcomes in the numeric range [0 .. 255].
41
+ /// Consumes 1 byte of entropy.
42
+ public func byte() : ?Nat8 {
43
+ it.next()
44
+ };
45
+
46
+ /// Bool iterator splitting up a byte of entropy into 8 bits
47
+ let bit : I.Iter<Bool> = object {
48
+ var mask = 0x80 : Nat8;
49
+ var byte = 0x00 : Nat8;
50
+ public func next() : ?Bool {
51
+ if (0 : Nat8 == mask) {
52
+ switch (it.next()) {
53
+ case null { null };
54
+ case (?w) {
55
+ byte := w;
56
+ mask := 0x40;
57
+ ?(0 : Nat8 != byte & (0x80 : Nat8))
58
+ }
59
+ }
60
+ } else {
61
+ let m = mask;
62
+ mask >>= (1 : Nat8);
63
+ ?(0 : Nat8 != byte & m)
64
+ }
65
+ }
66
+ };
67
+
68
+ /// Simulates a coin toss. Both outcomes have equal probability.
69
+ /// Consumes 1 bit of entropy (amortised).
70
+ public func coin() : ?Bool {
71
+ bit.next()
72
+ };
73
+
74
+ /// Uniformly distributes outcomes in the numeric range [0 .. 2^p - 1].
75
+ /// Consumes ⌈p/8⌉ bytes of entropy.
76
+ public func range(p : Nat8) : ?Nat {
77
+ var pp = p;
78
+ var acc : Nat = 0;
79
+ for (i in it) {
80
+ if (8 : Nat8 <= pp)
81
+ { acc := acc * 256 + Prim.nat8ToNat(i) }
82
+ else if (0 : Nat8 == pp)
83
+ { return ?acc }
84
+ else {
85
+ acc *= Prim.nat8ToNat(1 << pp);
86
+ let mask : Nat8 = 0xff >> (8 - pp);
87
+ return ?(acc + Prim.nat8ToNat(i & mask))
88
+ };
89
+ pp -= 8
90
+ };
91
+ null
92
+ };
93
+
94
+ /// Counts the number of heads in `n` fair coin tosses.
95
+ /// Consumes ⌈p/8⌉ bytes of entropy.
96
+ public func binomial(n : Nat8) : ?Nat8 {
97
+ var nn = n;
98
+ var acc : Nat8 = 0;
99
+ for (i in it) {
100
+ if (8 : Nat8 <= nn)
101
+ { acc +%= Prim.popcntNat8(i) }
102
+ else if (0 : Nat8 == nn)
103
+ { return ?acc }
104
+ else {
105
+ let mask : Nat8 = 0xff << (8 - nn);
106
+ let residue = Prim.popcntNat8(i & mask);
107
+ return ?(acc +% residue)
108
+ };
109
+ nn -= 8
110
+ };
111
+ null
112
+ }
113
+ };
114
+
115
+ let raw_rand = (actor "aaaaa-aa" : actor { raw_rand : () -> async Blob }).raw_rand;
116
+
117
+ /// Distributes outcomes in the numeric range [0 .. 255].
118
+ /// Seed blob must contain at least a byte.
119
+ public func byteFrom(seed : Blob) : Nat8 {
120
+ switch (seed.vals().next()) {
121
+ case (?w) { w };
122
+ case _ { P.unreachable() };
123
+ }
124
+ };
125
+
126
+ /// Simulates a coin toss.
127
+ /// Seed blob must contain at least a byte.
128
+ public func coinFrom(seed : Blob) : Bool {
129
+ switch (seed.vals().next()) {
130
+ case (?w) { w > (127 : Nat8) };
131
+ case _ { P.unreachable() };
132
+ }
133
+ };
134
+
135
+ /// Obtains a full blob (32 bytes) worth of fresh entropy.
136
+ public let blob : shared () -> async Blob = raw_rand;
137
+
138
+ /// Distributes outcomes in the numeric range [0 .. 2^p - 1].
139
+ /// Seed blob must contain at least ((p+7) / 8) bytes.
140
+ public func rangeFrom(p : Nat8, seed : Blob) : Nat {
141
+ rangeIter(p, seed.vals())
142
+ };
143
+
144
+ // internal worker method, expects iterator with sufficient supply
145
+ func rangeIter(p : Nat8, it : I.Iter<Nat8>) : Nat {
146
+ var pp = p;
147
+ var acc : Nat = 0;
148
+ for (i in it) {
149
+ if (8 : Nat8 <= pp)
150
+ { acc := acc * 256 + Prim.nat8ToNat(i) }
151
+ else if (0 : Nat8 == pp)
152
+ { return acc }
153
+ else {
154
+ acc *= Prim.nat8ToNat(1 << pp);
155
+ let mask : Nat8 = 0xff >> (8 - pp);
156
+ return acc + Prim.nat8ToNat(i & mask)
157
+ };
158
+ pp -= 8
159
+ };
160
+ P.unreachable()
161
+ };
162
+
163
+ /// Counts the number of heads in `n` coin tosses.
164
+ /// Seed blob must contain at least ((n+7) / 8) bytes.
165
+ public func binomialFrom(n : Nat8, seed : Blob) : Nat8 {
166
+ binomialIter(n, seed.vals())
167
+ };
168
+
169
+ // internal worker method, expects iterator with sufficient supply
170
+ func binomialIter(n : Nat8, it : I.Iter<Nat8>) : Nat8 {
171
+ var nn = n;
172
+ var acc : Nat8 = 0;
173
+ for (i in it) {
174
+ if (8 : Nat8 <= nn)
175
+ { acc +%= Prim.popcntNat8(i) }
176
+ else if (0 : Nat8 == nn)
177
+ { return acc }
178
+ else {
179
+ let mask : Nat8 = 0xff << (8 - nn);
180
+ let residue = Prim.popcntNat8(i & mask);
181
+ return (acc +% residue)
182
+ };
183
+ nn -= 8
184
+ };
185
+ P.unreachable()
186
+ }
187
+
188
+ }