ic-mops 0.8.5 → 0.8.7
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/package.json +3 -1
- package/.mops/base@0.7.4/LICENSE +0 -208
- package/.mops/base@0.7.4/README.md +0 -64
- package/.mops/base@0.7.4/mops.toml +0 -5
- package/.mops/base@0.7.4/src/Array.mo +0 -686
- package/.mops/base@0.7.4/src/AssocList.mo +0 -203
- package/.mops/base@0.7.4/src/Blob.mo +0 -55
- package/.mops/base@0.7.4/src/Bool.mo +0 -44
- package/.mops/base@0.7.4/src/Buffer.mo +0 -1937
- package/.mops/base@0.7.4/src/CertifiedData.mo +0 -29
- package/.mops/base@0.7.4/src/Char.mo +0 -67
- package/.mops/base@0.7.4/src/Debug.mo +0 -15
- package/.mops/base@0.7.4/src/Deque.mo +0 -75
- package/.mops/base@0.7.4/src/Error.mo +0 -41
- package/.mops/base@0.7.4/src/ExperimentalCycles.mo +0 -51
- package/.mops/base@0.7.4/src/ExperimentalInternetComputer.mo +0 -36
- package/.mops/base@0.7.4/src/ExperimentalStableMemory.mo +0 -121
- package/.mops/base@0.7.4/src/Float.mo +0 -150
- package/.mops/base@0.7.4/src/Func.mo +0 -38
- package/.mops/base@0.7.4/src/Hash.mo +0 -83
- package/.mops/base@0.7.4/src/HashMap.mo +0 -229
- package/.mops/base@0.7.4/src/Heap.mo +0 -113
- package/.mops/base@0.7.4/src/Int.mo +0 -150
- package/.mops/base@0.7.4/src/Int16.mo +0 -159
- package/.mops/base@0.7.4/src/Int32.mo +0 -160
- package/.mops/base@0.7.4/src/Int64.mo +0 -161
- package/.mops/base@0.7.4/src/Int8.mo +0 -160
- package/.mops/base@0.7.4/src/Iter.mo +0 -220
- package/.mops/base@0.7.4/src/IterType.mo +0 -7
- package/.mops/base@0.7.4/src/List.mo +0 -433
- package/.mops/base@0.7.4/src/Nat.mo +0 -75
- package/.mops/base@0.7.4/src/Nat16.mo +0 -146
- package/.mops/base@0.7.4/src/Nat32.mo +0 -146
- package/.mops/base@0.7.4/src/Nat64.mo +0 -146
- package/.mops/base@0.7.4/src/Nat8.mo +0 -146
- package/.mops/base@0.7.4/src/None.mo +0 -19
- package/.mops/base@0.7.4/src/Option.mo +0 -160
- package/.mops/base@0.7.4/src/Order.mo +0 -46
- package/.mops/base@0.7.4/src/Prelude.mo +0 -33
- package/.mops/base@0.7.4/src/Principal.mo +0 -58
- package/.mops/base@0.7.4/src/RBTree.mo +0 -218
- package/.mops/base@0.7.4/src/Random.mo +0 -188
- package/.mops/base@0.7.4/src/Result.mo +0 -210
- package/.mops/base@0.7.4/src/Stack.mo +0 -40
- package/.mops/base@0.7.4/src/Text.mo +0 -615
- package/.mops/base@0.7.4/src/Time.mo +0 -37
- package/.mops/base@0.7.4/src/Trie.mo +0 -1200
- package/.mops/base@0.7.4/src/TrieMap.mo +0 -180
- package/.mops/base@0.7.4/src/TrieSet.mo +0 -97
- package/.mops/base@0.8.3/LICENSE +0 -208
- package/.mops/base@0.8.3/README.md +0 -64
- package/.mops/base@0.8.3/mops.toml +0 -6
- package/.mops/base@0.8.3/src/Array.mo +0 -717
- package/.mops/base@0.8.3/src/AssocList.mo +0 -404
- package/.mops/base@0.8.3/src/Blob.mo +0 -212
- package/.mops/base@0.8.3/src/Bool.mo +0 -44
- package/.mops/base@0.8.3/src/Buffer.mo +0 -2660
- package/.mops/base@0.8.3/src/CertifiedData.mo +0 -53
- package/.mops/base@0.8.3/src/Char.mo +0 -65
- package/.mops/base@0.8.3/src/Debug.mo +0 -56
- package/.mops/base@0.8.3/src/Deque.mo +0 -243
- package/.mops/base@0.8.3/src/Error.mo +0 -68
- package/.mops/base@0.8.3/src/ExperimentalCycles.mo +0 -151
- package/.mops/base@0.8.3/src/ExperimentalInternetComputer.mo +0 -60
- package/.mops/base@0.8.3/src/ExperimentalStableMemory.mo +0 -348
- package/.mops/base@0.8.3/src/Float.mo +0 -843
- package/.mops/base@0.8.3/src/Func.mo +0 -46
- package/.mops/base@0.8.3/src/Hash.mo +0 -82
- package/.mops/base@0.8.3/src/HashMap.mo +0 -457
- package/.mops/base@0.8.3/src/Heap.mo +0 -233
- package/.mops/base@0.8.3/src/Int.mo +0 -365
- package/.mops/base@0.8.3/src/Int16.mo +0 -521
- package/.mops/base@0.8.3/src/Int32.mo +0 -522
- package/.mops/base@0.8.3/src/Int64.mo +0 -522
- package/.mops/base@0.8.3/src/Int8.mo +0 -522
- package/.mops/base@0.8.3/src/Iter.mo +0 -227
- package/.mops/base@0.8.3/src/IterType.mo +0 -7
- package/.mops/base@0.8.3/src/List.mo +0 -930
- package/.mops/base@0.8.3/src/Nat.mo +0 -305
- package/.mops/base@0.8.3/src/Nat16.mo +0 -144
- package/.mops/base@0.8.3/src/Nat32.mo +0 -144
- package/.mops/base@0.8.3/src/Nat64.mo +0 -144
- package/.mops/base@0.8.3/src/Nat8.mo +0 -144
- package/.mops/base@0.8.3/src/None.mo +0 -19
- package/.mops/base@0.8.3/src/Option.mo +0 -154
- package/.mops/base@0.8.3/src/Order.mo +0 -46
- package/.mops/base@0.8.3/src/Prelude.mo +0 -33
- package/.mops/base@0.8.3/src/Principal.mo +0 -249
- package/.mops/base@0.8.3/src/RBTree.mo +0 -681
- package/.mops/base@0.8.3/src/Random.mo +0 -270
- package/.mops/base@0.8.3/src/Result.mo +0 -209
- package/.mops/base@0.8.3/src/Stack.mo +0 -93
- package/.mops/base@0.8.3/src/Text.mo +0 -761
- package/.mops/base@0.8.3/src/Time.mo +0 -36
- package/.mops/base@0.8.3/src/Timer.mo +0 -62
- package/.mops/base@0.8.3/src/Trie.mo +0 -1603
- package/.mops/base@0.8.3/src/TrieMap.mo +0 -392
- package/.mops/base@0.8.3/src/TrieSet.mo +0 -148
- package/network.txt +0 -1
|
@@ -1,270 +0,0 @@
|
|
|
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
|
-
/// Usage:
|
|
25
|
-
/// ```motoko no-repl
|
|
26
|
-
/// import Random "mo:base/Random";
|
|
27
|
-
/// ```
|
|
28
|
-
|
|
29
|
-
import I "Iter";
|
|
30
|
-
import Option "Option";
|
|
31
|
-
import Prim "mo:⛔";
|
|
32
|
-
|
|
33
|
-
module {
|
|
34
|
-
|
|
35
|
-
let raw_rand = (actor "aaaaa-aa" : actor { raw_rand : () -> async Blob }).raw_rand;
|
|
36
|
-
|
|
37
|
-
/// Obtains a full blob (32 bytes) worth of fresh entropy.
|
|
38
|
-
///
|
|
39
|
-
/// Example:
|
|
40
|
-
/// ```motoko no-repl
|
|
41
|
-
/// let random = Random.Finite(await Random.blob());
|
|
42
|
-
/// ```
|
|
43
|
-
public let blob : shared () -> async Blob = raw_rand;
|
|
44
|
-
|
|
45
|
-
/// Drawing from a finite supply of entropy, `Finite` provides
|
|
46
|
-
/// methods to obtain random values. When the entropy is used up,
|
|
47
|
-
/// `null` is returned. Otherwise the outcomes' distributions are
|
|
48
|
-
/// stated for each method. The uniformity of outcomes is
|
|
49
|
-
/// guaranteed only when the supplied entropy is originally obtained
|
|
50
|
-
/// by the `blob()` call, and is never reused.
|
|
51
|
-
///
|
|
52
|
-
/// Example:
|
|
53
|
-
/// ```motoko no-repl
|
|
54
|
-
/// import Random "mo:base/Random";
|
|
55
|
-
///
|
|
56
|
-
/// let random = Random.Finite(await Random.blob());
|
|
57
|
-
///
|
|
58
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
59
|
-
/// let seedRandom = Random.Finite(seed);
|
|
60
|
-
/// ```
|
|
61
|
-
public class Finite(entropy : Blob) {
|
|
62
|
-
let it : I.Iter<Nat8> = entropy.vals();
|
|
63
|
-
|
|
64
|
-
/// Uniformly distributes outcomes in the numeric range [0 .. 255].
|
|
65
|
-
/// Consumes 1 byte of entropy.
|
|
66
|
-
///
|
|
67
|
-
/// Example:
|
|
68
|
-
/// ```motoko no-repl
|
|
69
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
70
|
-
/// let random = Random.Finite(seed);
|
|
71
|
-
/// random.byte() // => ?20
|
|
72
|
-
/// ```
|
|
73
|
-
public func byte() : ?Nat8 {
|
|
74
|
-
it.next()
|
|
75
|
-
};
|
|
76
|
-
|
|
77
|
-
/// Bool iterator splitting up a byte of entropy into 8 bits
|
|
78
|
-
let bit : I.Iter<Bool> = object {
|
|
79
|
-
var mask = 0x00 : Nat8;
|
|
80
|
-
var byte = 0x00 : Nat8;
|
|
81
|
-
public func next() : ?Bool {
|
|
82
|
-
if (0 : Nat8 == mask) {
|
|
83
|
-
switch (it.next()) {
|
|
84
|
-
case null { null };
|
|
85
|
-
case (?w) {
|
|
86
|
-
byte := w;
|
|
87
|
-
mask := 0x40;
|
|
88
|
-
?(0 : Nat8 != byte & (0x80 : Nat8))
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
} else {
|
|
92
|
-
let m = mask;
|
|
93
|
-
mask >>= (1 : Nat8);
|
|
94
|
-
?(0 : Nat8 != byte & m)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/// Simulates a coin toss. Both outcomes have equal probability.
|
|
100
|
-
/// Consumes 1 bit of entropy (amortised).
|
|
101
|
-
///
|
|
102
|
-
/// Example:
|
|
103
|
-
/// ```motoko no-repl
|
|
104
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
105
|
-
/// let random = Random.Finite(seed);
|
|
106
|
-
/// random.coin() // => ?false
|
|
107
|
-
/// ```
|
|
108
|
-
public func coin() : ?Bool {
|
|
109
|
-
bit.next()
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
/// Uniformly distributes outcomes in the numeric range [0 .. 2^p - 1].
|
|
113
|
-
/// Consumes ⌈p/8⌉ bytes of entropy.
|
|
114
|
-
///
|
|
115
|
-
/// Example:
|
|
116
|
-
/// ```motoko no-repl
|
|
117
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
118
|
-
/// let random = Random.Finite(seed);
|
|
119
|
-
/// random.range(32) // => ?348746249
|
|
120
|
-
/// ```
|
|
121
|
-
public func range(p : Nat8) : ?Nat {
|
|
122
|
-
var pp = p;
|
|
123
|
-
var acc : Nat = 0;
|
|
124
|
-
for (i in it) {
|
|
125
|
-
if (8 : Nat8 <= pp) {
|
|
126
|
-
acc := acc * 256 + Prim.nat8ToNat(i)
|
|
127
|
-
}
|
|
128
|
-
else if (0 : Nat8 == pp) {
|
|
129
|
-
return ?acc
|
|
130
|
-
} else {
|
|
131
|
-
acc *= Prim.nat8ToNat(1 << pp);
|
|
132
|
-
let mask : Nat8 = 0xff >> (8 - pp);
|
|
133
|
-
return ?(acc + Prim.nat8ToNat(i & mask))
|
|
134
|
-
};
|
|
135
|
-
pp -= 8
|
|
136
|
-
};
|
|
137
|
-
if (0 : Nat8 == pp)
|
|
138
|
-
?acc
|
|
139
|
-
else null
|
|
140
|
-
};
|
|
141
|
-
|
|
142
|
-
/// Counts the number of heads in `n` fair coin tosses.
|
|
143
|
-
/// Consumes ⌈n/8⌉ bytes of entropy.
|
|
144
|
-
///
|
|
145
|
-
/// Example:
|
|
146
|
-
/// ```motoko no-repl
|
|
147
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
148
|
-
/// let random = Random.Finite(seed);
|
|
149
|
-
/// random.binomial(5) // => ?1
|
|
150
|
-
/// ```
|
|
151
|
-
public func binomial(n : Nat8) : ?Nat8 {
|
|
152
|
-
var nn = n;
|
|
153
|
-
var acc : Nat8 = 0;
|
|
154
|
-
for (i in it) {
|
|
155
|
-
if (8 : Nat8 <= nn) {
|
|
156
|
-
acc +%= Prim.popcntNat8(i)
|
|
157
|
-
} else if (0 : Nat8 == nn) {
|
|
158
|
-
return ?acc
|
|
159
|
-
} else {
|
|
160
|
-
let mask : Nat8 = 0xff << (8 - nn);
|
|
161
|
-
let residue = Prim.popcntNat8(i & mask);
|
|
162
|
-
return ?(acc +% residue)
|
|
163
|
-
};
|
|
164
|
-
nn -= 8
|
|
165
|
-
};
|
|
166
|
-
if (0 : Nat8 == nn)
|
|
167
|
-
?acc
|
|
168
|
-
else null
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
/// Distributes outcomes in the numeric range [0 .. 255].
|
|
173
|
-
/// Seed blob must contain at least a byte.
|
|
174
|
-
///
|
|
175
|
-
/// Example:
|
|
176
|
-
/// ```motoko no-repl
|
|
177
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
178
|
-
/// Random.byteFrom(seed) // => 20
|
|
179
|
-
/// ```
|
|
180
|
-
public func byteFrom(seed : Blob) : Nat8 {
|
|
181
|
-
switch (seed.vals().next()) {
|
|
182
|
-
case (?w) { w };
|
|
183
|
-
case _ { Prim.trap "Random.byteFrom" }
|
|
184
|
-
}
|
|
185
|
-
};
|
|
186
|
-
|
|
187
|
-
/// Simulates a coin toss.
|
|
188
|
-
/// Seed blob must contain at least a byte.
|
|
189
|
-
///
|
|
190
|
-
/// Example:
|
|
191
|
-
/// ```motoko no-repl
|
|
192
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
193
|
-
/// Random.coinFrom(seed) // => false
|
|
194
|
-
/// ```
|
|
195
|
-
public func coinFrom(seed : Blob) : Bool {
|
|
196
|
-
switch (seed.vals().next()) {
|
|
197
|
-
case (?w) { w > (127 : Nat8) };
|
|
198
|
-
case _ { Prim.trap "Random.coinFrom" }
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
|
|
202
|
-
/// Distributes outcomes in the numeric range [0 .. 2^p - 1].
|
|
203
|
-
/// Seed blob must contain at least ((p+7) / 8) bytes.
|
|
204
|
-
///
|
|
205
|
-
/// Example:
|
|
206
|
-
/// ```motoko no-repl
|
|
207
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
208
|
-
/// Random.rangeFrom(32, seed) // => 348746249
|
|
209
|
-
/// ```
|
|
210
|
-
public func rangeFrom(p : Nat8, seed : Blob) : Nat {
|
|
211
|
-
rangeIter(p, seed.vals())
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
// internal worker method, expects iterator with sufficient supply
|
|
215
|
-
func rangeIter(p : Nat8, it : I.Iter<Nat8>) : Nat {
|
|
216
|
-
var pp = p;
|
|
217
|
-
var acc : Nat = 0;
|
|
218
|
-
for (i in it) {
|
|
219
|
-
if (8 : Nat8 <= pp) {
|
|
220
|
-
acc := acc * 256 + Prim.nat8ToNat(i)
|
|
221
|
-
} else if (0 : Nat8 == pp) {
|
|
222
|
-
return acc
|
|
223
|
-
} else {
|
|
224
|
-
acc *= Prim.nat8ToNat(1 << pp);
|
|
225
|
-
let mask : Nat8 = 0xff >> (8 - pp);
|
|
226
|
-
return acc + Prim.nat8ToNat(i & mask)
|
|
227
|
-
};
|
|
228
|
-
pp -= 8
|
|
229
|
-
};
|
|
230
|
-
if (0 : Nat8 == pp) {
|
|
231
|
-
return acc
|
|
232
|
-
}
|
|
233
|
-
else Prim.trap("Random.rangeFrom")
|
|
234
|
-
};
|
|
235
|
-
|
|
236
|
-
/// Counts the number of heads in `n` coin tosses.
|
|
237
|
-
/// Seed blob must contain at least ((n+7) / 8) bytes.
|
|
238
|
-
///
|
|
239
|
-
/// Example:
|
|
240
|
-
/// ```motoko no-repl
|
|
241
|
-
/// let seed : Blob = "\14\C9\72\09\03\D4\D5\72\82\95\E5\43\AF\FA\A9\44\49\2F\25\56\13\F3\6E\C7\B0\87\DC\76\08\69\14\CF";
|
|
242
|
-
/// Random.binomialFrom(5, seed) // => 1
|
|
243
|
-
/// ```
|
|
244
|
-
public func binomialFrom(n : Nat8, seed : Blob) : Nat8 {
|
|
245
|
-
binomialIter(n, seed.vals())
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
// internal worker method, expects iterator with sufficient supply
|
|
249
|
-
func binomialIter(n : Nat8, it : I.Iter<Nat8>) : Nat8 {
|
|
250
|
-
var nn = n;
|
|
251
|
-
var acc : Nat8 = 0;
|
|
252
|
-
for (i in it) {
|
|
253
|
-
if (8 : Nat8 <= nn) {
|
|
254
|
-
acc +%= Prim.popcntNat8(i)
|
|
255
|
-
} else if (0 : Nat8 == nn) {
|
|
256
|
-
return acc
|
|
257
|
-
} else {
|
|
258
|
-
let mask : Nat8 = 0xff << (8 - nn);
|
|
259
|
-
let residue = Prim.popcntNat8(i & mask);
|
|
260
|
-
return (acc +% residue)
|
|
261
|
-
};
|
|
262
|
-
nn -= 8
|
|
263
|
-
};
|
|
264
|
-
if (0 : Nat8 == nn) {
|
|
265
|
-
return acc
|
|
266
|
-
}
|
|
267
|
-
else Prim.trap("Random.binomialFrom")
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
/// Error handling with the Result type.
|
|
2
|
-
|
|
3
|
-
import Prim "mo:⛔";
|
|
4
|
-
import P "Prelude";
|
|
5
|
-
import Order "Order";
|
|
6
|
-
|
|
7
|
-
module {
|
|
8
|
-
|
|
9
|
-
/// `Result<Ok, Err>` is the type used for returning and propagating errors. It
|
|
10
|
-
/// is a type with the variants, `#ok(Ok)`, representing success and containing
|
|
11
|
-
/// a value, and `#err(Err)`, representing error and containing an error value.
|
|
12
|
-
///
|
|
13
|
-
/// The simplest way of working with `Result`s is to pattern match on them:
|
|
14
|
-
///
|
|
15
|
-
/// For example, given a function `createUser(user : User) : Result<Id, String>`
|
|
16
|
-
/// where `String` is an error message we could use it like so:
|
|
17
|
-
/// ```motoko no-repl
|
|
18
|
-
/// switch(createUser(myUser)) {
|
|
19
|
-
/// case (#ok(id)) { Debug.print("Created new user with id: " # id) };
|
|
20
|
-
/// case (#err(msg)) { Debug.print("Failed to create user with the error: " # msg) };
|
|
21
|
-
/// }
|
|
22
|
-
/// ```
|
|
23
|
-
public type Result<Ok, Err> = {
|
|
24
|
-
#ok : Ok;
|
|
25
|
-
#err : Err
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
// Compares two Result's for equality.
|
|
29
|
-
public func equal<Ok, Err>(
|
|
30
|
-
eqOk : (Ok, Ok) -> Bool,
|
|
31
|
-
eqErr : (Err, Err) -> Bool,
|
|
32
|
-
r1 : Result<Ok, Err>,
|
|
33
|
-
r2 : Result<Ok, Err>
|
|
34
|
-
) : Bool {
|
|
35
|
-
switch (r1, r2) {
|
|
36
|
-
case (#ok(ok1), #ok(ok2)) {
|
|
37
|
-
eqOk(ok1, ok2)
|
|
38
|
-
};
|
|
39
|
-
case (#err(err1), #err(err2)) {
|
|
40
|
-
eqErr(err1, err2)
|
|
41
|
-
};
|
|
42
|
-
case _ { false }
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// Compares two Results. `#ok` is larger than `#err`. This ordering is
|
|
47
|
-
// arbitrary, but it lets you for example use Results as keys in ordered maps.
|
|
48
|
-
public func compare<Ok, Err>(
|
|
49
|
-
compareOk : (Ok, Ok) -> Order.Order,
|
|
50
|
-
compareErr : (Err, Err) -> Order.Order,
|
|
51
|
-
r1 : Result<Ok, Err>,
|
|
52
|
-
r2 : Result<Ok, Err>
|
|
53
|
-
) : Order.Order {
|
|
54
|
-
switch (r1, r2) {
|
|
55
|
-
case (#ok(ok1), #ok(ok2)) {
|
|
56
|
-
compareOk(ok1, ok2)
|
|
57
|
-
};
|
|
58
|
-
case (#err(err1), #err(err2)) {
|
|
59
|
-
compareErr(err1, err2)
|
|
60
|
-
};
|
|
61
|
-
case (#ok(_), _) { #greater };
|
|
62
|
-
case (#err(_), _) { #less }
|
|
63
|
-
}
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
/// Allows sequencing of `Result` values and functions that return
|
|
67
|
-
/// `Result`'s themselves.
|
|
68
|
-
/// ```motoko
|
|
69
|
-
/// import Result "mo:base/Result";
|
|
70
|
-
/// type Result<T,E> = Result.Result<T, E>;
|
|
71
|
-
/// func largerThan10(x : Nat) : Result<Nat, Text> =
|
|
72
|
-
/// if (x > 10) { #ok(x) } else { #err("Not larger than 10.") };
|
|
73
|
-
///
|
|
74
|
-
/// func smallerThan20(x : Nat) : Result<Nat, Text> =
|
|
75
|
-
/// if (x < 20) { #ok(x) } else { #err("Not smaller than 20.") };
|
|
76
|
-
///
|
|
77
|
-
/// func between10And20(x : Nat) : Result<Nat, Text> =
|
|
78
|
-
/// Result.chain(largerThan10(x), smallerThan20);
|
|
79
|
-
///
|
|
80
|
-
/// assert(between10And20(15) == #ok(15));
|
|
81
|
-
/// assert(between10And20(9) == #err("Not larger than 10."));
|
|
82
|
-
/// assert(between10And20(21) == #err("Not smaller than 20."));
|
|
83
|
-
/// ```
|
|
84
|
-
public func chain<R1, R2, Error>(
|
|
85
|
-
x : Result<R1, Error>,
|
|
86
|
-
y : R1 -> Result<R2, Error>
|
|
87
|
-
) : Result<R2, Error> {
|
|
88
|
-
switch x {
|
|
89
|
-
case (#err(e)) { #err(e) };
|
|
90
|
-
case (#ok(r)) { y(r) }
|
|
91
|
-
}
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/// Flattens a nested Result.
|
|
95
|
-
///
|
|
96
|
-
/// ```motoko
|
|
97
|
-
/// import Result "mo:base/Result";
|
|
98
|
-
/// assert(Result.flatten<Nat, Text>(#ok(#ok(10))) == #ok(10));
|
|
99
|
-
/// assert(Result.flatten<Nat, Text>(#err("Wrong")) == #err("Wrong"));
|
|
100
|
-
/// assert(Result.flatten<Nat, Text>(#ok(#err("Wrong"))) == #err("Wrong"));
|
|
101
|
-
/// ```
|
|
102
|
-
public func flatten<Ok, Error>(
|
|
103
|
-
result : Result<Result<Ok, Error>, Error>
|
|
104
|
-
) : Result<Ok, Error> {
|
|
105
|
-
switch result {
|
|
106
|
-
case (#ok(ok)) { ok };
|
|
107
|
-
case (#err(err)) { #err(err) }
|
|
108
|
-
}
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
/// Maps the `Ok` type/value, leaving any `Error` type/value unchanged.
|
|
112
|
-
public func mapOk<Ok1, Ok2, Error>(
|
|
113
|
-
x : Result<Ok1, Error>,
|
|
114
|
-
f : Ok1 -> Ok2
|
|
115
|
-
) : Result<Ok2, Error> {
|
|
116
|
-
switch x {
|
|
117
|
-
case (#err(e)) { #err(e) };
|
|
118
|
-
case (#ok(r)) { #ok(f(r)) }
|
|
119
|
-
}
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
/// Maps the `Err` type/value, leaving any `Ok` type/value unchanged.
|
|
123
|
-
public func mapErr<Ok, Error1, Error2>(
|
|
124
|
-
x : Result<Ok, Error1>,
|
|
125
|
-
f : Error1 -> Error2
|
|
126
|
-
) : Result<Ok, Error2> {
|
|
127
|
-
switch x {
|
|
128
|
-
case (#err(e)) { #err(f(e)) };
|
|
129
|
-
case (#ok(r)) { #ok(r) }
|
|
130
|
-
}
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
/// Create a result from an option, including an error value to handle the `null` case.
|
|
134
|
-
/// ```motoko
|
|
135
|
-
/// import Result "mo:base/Result";
|
|
136
|
-
/// assert(Result.fromOption(?42, "err") == #ok(42));
|
|
137
|
-
/// assert(Result.fromOption(null, "err") == #err("err"));
|
|
138
|
-
/// ```
|
|
139
|
-
public func fromOption<R, E>(x : ?R, err : E) : Result<R, E> {
|
|
140
|
-
switch x {
|
|
141
|
-
case (?x) { #ok(x) };
|
|
142
|
-
case null { #err(err) }
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
|
|
146
|
-
/// Create an option from a result, turning all #err into `null`.
|
|
147
|
-
/// ```motoko
|
|
148
|
-
/// import Result "mo:base/Result";
|
|
149
|
-
/// assert(Result.toOption(#ok(42)) == ?42);
|
|
150
|
-
/// assert(Result.toOption(#err("err")) == null);
|
|
151
|
-
/// ```
|
|
152
|
-
public func toOption<R, E>(r : Result<R, E>) : ?R {
|
|
153
|
-
switch r {
|
|
154
|
-
case (#ok(x)) { ?x };
|
|
155
|
-
case (#err(_)) { null }
|
|
156
|
-
}
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
/// Applies a function to a successful value, but discards the result. Use
|
|
160
|
-
/// `iterate` if you're only interested in the side effect `f` produces.
|
|
161
|
-
///
|
|
162
|
-
/// ```motoko
|
|
163
|
-
/// import Result "mo:base/Result";
|
|
164
|
-
/// var counter : Nat = 0;
|
|
165
|
-
/// Result.iterate<Nat, Text>(#ok(5), func (x : Nat) { counter += x });
|
|
166
|
-
/// assert(counter == 5);
|
|
167
|
-
/// Result.iterate<Nat, Text>(#err("Wrong"), func (x : Nat) { counter += x });
|
|
168
|
-
/// assert(counter == 5);
|
|
169
|
-
/// ```
|
|
170
|
-
public func iterate<Ok, Err>(res : Result<Ok, Err>, f : Ok -> ()) {
|
|
171
|
-
switch res {
|
|
172
|
-
case (#ok(ok)) { f(ok) };
|
|
173
|
-
case _ {}
|
|
174
|
-
}
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
// Whether this Result is an `#ok`
|
|
178
|
-
public func isOk(r : Result<Any, Any>) : Bool {
|
|
179
|
-
switch r {
|
|
180
|
-
case (#ok(_)) { true };
|
|
181
|
-
case (#err(_)) { false }
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
// Whether this Result is an `#err`
|
|
186
|
-
public func isErr(r : Result<Any, Any>) : Bool {
|
|
187
|
-
switch r {
|
|
188
|
-
case (#ok(_)) { false };
|
|
189
|
-
case (#err(_)) { true }
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
/// Asserts that its argument is an `#ok` result, traps otherwise.
|
|
194
|
-
public func assertOk(r : Result<Any, Any>) {
|
|
195
|
-
switch (r) {
|
|
196
|
-
case (#err(_)) { assert false };
|
|
197
|
-
case (#ok(_)) {}
|
|
198
|
-
}
|
|
199
|
-
};
|
|
200
|
-
|
|
201
|
-
/// Asserts that its argument is an `#err` result, traps otherwise.
|
|
202
|
-
public func assertErr(r : Result<Any, Any>) {
|
|
203
|
-
switch (r) {
|
|
204
|
-
case (#err(_)) {};
|
|
205
|
-
case (#ok(_)) assert false
|
|
206
|
-
}
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
}
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
/// Class `Stack<X>` provides a Minimal LIFO stack of elements of type `X`.
|
|
2
|
-
///
|
|
3
|
-
/// See library `Deque` for mixed LIFO/FIFO behavior.
|
|
4
|
-
///
|
|
5
|
-
/// Example:
|
|
6
|
-
/// ```motoko name=initialize
|
|
7
|
-
/// import Stack "mo:base/Stack";
|
|
8
|
-
///
|
|
9
|
-
/// let stack = Stack.Stack<Nat>(); // create a stack
|
|
10
|
-
/// ```
|
|
11
|
-
/// Runtime: O(1)
|
|
12
|
-
///
|
|
13
|
-
/// Space: O(1)
|
|
14
|
-
|
|
15
|
-
import List "List";
|
|
16
|
-
|
|
17
|
-
module {
|
|
18
|
-
|
|
19
|
-
public class Stack<T>() {
|
|
20
|
-
|
|
21
|
-
var stack : List.List<T> = List.nil<T>();
|
|
22
|
-
|
|
23
|
-
/// Push an element on the top of the stack.
|
|
24
|
-
///
|
|
25
|
-
/// Example:
|
|
26
|
-
/// ```motoko include=initialize
|
|
27
|
-
/// stack.push(1);
|
|
28
|
-
/// stack.push(2);
|
|
29
|
-
/// stack.push(3);
|
|
30
|
-
/// stack.peek(); // examine the top most element
|
|
31
|
-
/// ```
|
|
32
|
-
///
|
|
33
|
-
/// Runtime: O(1)
|
|
34
|
-
///
|
|
35
|
-
/// Space: O(1)
|
|
36
|
-
public func push(x : T) {
|
|
37
|
-
stack := ?(x, stack)
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/// True when the stack is empty and false otherwise.
|
|
41
|
-
///
|
|
42
|
-
/// Example:
|
|
43
|
-
/// ```motoko include=initialize
|
|
44
|
-
/// stack.isEmpty();
|
|
45
|
-
/// ```
|
|
46
|
-
///
|
|
47
|
-
/// Runtime: O(1)
|
|
48
|
-
///
|
|
49
|
-
/// Space: O(1)
|
|
50
|
-
public func isEmpty() : Bool {
|
|
51
|
-
List.isNil<T>(stack)
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
/// Return (without removing) the top element, or return null if the stack is empty.
|
|
55
|
-
///
|
|
56
|
-
/// Example:
|
|
57
|
-
/// ```motoko include=initialize
|
|
58
|
-
/// stack.push(1);
|
|
59
|
-
/// stack.push(2);
|
|
60
|
-
/// stack.push(3);
|
|
61
|
-
/// stack.peek();
|
|
62
|
-
/// ```
|
|
63
|
-
///
|
|
64
|
-
/// Runtime: O(1)
|
|
65
|
-
///
|
|
66
|
-
/// Space: O(1)
|
|
67
|
-
public func peek() : ?T {
|
|
68
|
-
switch stack {
|
|
69
|
-
case null { null };
|
|
70
|
-
case (?(h, t)) { ?h }
|
|
71
|
-
}
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/// Remove and return the top element, or return null if the stack is empty.
|
|
75
|
-
///
|
|
76
|
-
/// Example:
|
|
77
|
-
/// ```motoko include=initialize
|
|
78
|
-
/// stack.push(1);
|
|
79
|
-
/// ignore stack.pop();
|
|
80
|
-
/// stack.isEmpty();
|
|
81
|
-
/// ```
|
|
82
|
-
///
|
|
83
|
-
/// Runtime: O(1)
|
|
84
|
-
///
|
|
85
|
-
/// Space: O(1)
|
|
86
|
-
public func pop() : ?T {
|
|
87
|
-
switch stack {
|
|
88
|
-
case null { null };
|
|
89
|
-
case (?(h, t)) { stack := t; ?h }
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|