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.
- package/.mops/base@0.7.4/LICENSE +208 -0
- package/.mops/base@0.7.4/README.md +64 -0
- package/.mops/base@0.7.4/mops.toml +5 -0
- package/.mops/base@0.7.4/src/Array.mo +686 -0
- package/.mops/base@0.7.4/src/AssocList.mo +203 -0
- package/.mops/base@0.7.4/src/Blob.mo +55 -0
- package/.mops/base@0.7.4/src/Bool.mo +44 -0
- package/.mops/base@0.7.4/src/Buffer.mo +1937 -0
- package/.mops/base@0.7.4/src/CertifiedData.mo +29 -0
- package/.mops/base@0.7.4/src/Char.mo +67 -0
- package/.mops/base@0.7.4/src/Debug.mo +15 -0
- package/.mops/base@0.7.4/src/Deque.mo +75 -0
- package/.mops/base@0.7.4/src/Error.mo +41 -0
- package/.mops/base@0.7.4/src/ExperimentalCycles.mo +51 -0
- package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +36 -0
- package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +121 -0
- package/.mops/base@0.7.4/src/Float.mo +150 -0
- package/.mops/base@0.7.4/src/Func.mo +38 -0
- package/.mops/base@0.7.4/src/Hash.mo +83 -0
- package/.mops/base@0.7.4/src/HashMap.mo +229 -0
- package/.mops/base@0.7.4/src/Heap.mo +113 -0
- package/.mops/base@0.7.4/src/Int.mo +150 -0
- package/.mops/base@0.7.4/src/Int16.mo +159 -0
- package/.mops/base@0.7.4/src/Int32.mo +160 -0
- package/.mops/base@0.7.4/src/Int64.mo +161 -0
- package/.mops/base@0.7.4/src/Int8.mo +160 -0
- package/.mops/base@0.7.4/src/Iter.mo +220 -0
- package/.mops/base@0.7.4/src/IterType.mo +7 -0
- package/.mops/base@0.7.4/src/List.mo +433 -0
- package/.mops/base@0.7.4/src/Nat.mo +75 -0
- package/.mops/base@0.7.4/src/Nat16.mo +146 -0
- package/.mops/base@0.7.4/src/Nat32.mo +146 -0
- package/.mops/base@0.7.4/src/Nat64.mo +146 -0
- package/.mops/base@0.7.4/src/Nat8.mo +146 -0
- package/.mops/base@0.7.4/src/None.mo +19 -0
- package/.mops/base@0.7.4/src/Option.mo +160 -0
- package/.mops/base@0.7.4/src/Order.mo +46 -0
- package/.mops/base@0.7.4/src/Prelude.mo +33 -0
- package/.mops/base@0.7.4/src/Principal.mo +58 -0
- package/.mops/base@0.7.4/src/RBTree.mo +218 -0
- package/.mops/base@0.7.4/src/Random.mo +188 -0
- package/.mops/base@0.7.4/src/Result.mo +210 -0
- package/.mops/base@0.7.4/src/Stack.mo +40 -0
- package/.mops/base@0.7.4/src/Text.mo +615 -0
- package/.mops/base@0.7.4/src/Time.mo +37 -0
- package/.mops/base@0.7.4/src/Trie.mo +1200 -0
- package/.mops/base@0.7.4/src/TrieMap.mo +180 -0
- package/.mops/base@0.7.4/src/TrieSet.mo +97 -0
- package/.mops/base@0.8.3/LICENSE +208 -0
- package/.mops/base@0.8.3/README.md +64 -0
- package/.mops/base@0.8.3/mops.toml +6 -0
- package/.mops/base@0.8.3/src/Array.mo +717 -0
- package/.mops/base@0.8.3/src/AssocList.mo +404 -0
- package/.mops/base@0.8.3/src/Blob.mo +212 -0
- package/.mops/base@0.8.3/src/Bool.mo +44 -0
- package/.mops/base@0.8.3/src/Buffer.mo +2660 -0
- package/.mops/base@0.8.3/src/CertifiedData.mo +53 -0
- package/.mops/base@0.8.3/src/Char.mo +65 -0
- package/.mops/base@0.8.3/src/Debug.mo +56 -0
- package/.mops/base@0.8.3/src/Deque.mo +243 -0
- package/.mops/base@0.8.3/src/Error.mo +68 -0
- package/.mops/base@0.8.3/src/ExperimentalCycles.mo +151 -0
- package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +60 -0
- package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +348 -0
- package/.mops/base@0.8.3/src/Float.mo +843 -0
- package/.mops/base@0.8.3/src/Func.mo +46 -0
- package/.mops/base@0.8.3/src/Hash.mo +82 -0
- package/.mops/base@0.8.3/src/HashMap.mo +457 -0
- package/.mops/base@0.8.3/src/Heap.mo +233 -0
- package/.mops/base@0.8.3/src/Int.mo +365 -0
- package/.mops/base@0.8.3/src/Int16.mo +521 -0
- package/.mops/base@0.8.3/src/Int32.mo +522 -0
- package/.mops/base@0.8.3/src/Int64.mo +522 -0
- package/.mops/base@0.8.3/src/Int8.mo +522 -0
- package/.mops/base@0.8.3/src/Iter.mo +227 -0
- package/.mops/base@0.8.3/src/IterType.mo +7 -0
- package/.mops/base@0.8.3/src/List.mo +930 -0
- package/.mops/base@0.8.3/src/Nat.mo +305 -0
- package/.mops/base@0.8.3/src/Nat16.mo +144 -0
- package/.mops/base@0.8.3/src/Nat32.mo +144 -0
- package/.mops/base@0.8.3/src/Nat64.mo +144 -0
- package/.mops/base@0.8.3/src/Nat8.mo +144 -0
- package/.mops/base@0.8.3/src/None.mo +19 -0
- package/.mops/base@0.8.3/src/Option.mo +154 -0
- package/.mops/base@0.8.3/src/Order.mo +46 -0
- package/.mops/base@0.8.3/src/Prelude.mo +33 -0
- package/.mops/base@0.8.3/src/Principal.mo +249 -0
- package/.mops/base@0.8.3/src/RBTree.mo +681 -0
- package/.mops/base@0.8.3/src/Random.mo +270 -0
- package/.mops/base@0.8.3/src/Result.mo +209 -0
- package/.mops/base@0.8.3/src/Stack.mo +93 -0
- package/.mops/base@0.8.3/src/Text.mo +761 -0
- package/.mops/base@0.8.3/src/Time.mo +36 -0
- package/.mops/base@0.8.3/src/Timer.mo +62 -0
- package/.mops/base@0.8.3/src/Trie.mo +1603 -0
- package/.mops/base@0.8.3/src/TrieMap.mo +392 -0
- package/.mops/base@0.8.3/src/TrieSet.mo +148 -0
- package/mops.js +1 -1
- package/network.txt +1 -0
- 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
|
+
}
|