functionalscript 0.0.238 → 0.0.242

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.
@@ -0,0 +1,372 @@
1
+ const { compose, identity } = require('../function')
2
+ const operator = require('../function/operator')
3
+ const { logicalNot, strictEqual, stateScanToScan, reduceToScan, foldToScan } = require('../function/operator')
4
+
5
+ /**
6
+ * @template T
7
+ * @typedef {NotLazy<T> | Thunk<T>} List
8
+ */
9
+
10
+ /**
11
+ * @template T
12
+ * @typedef {|
13
+ * Result<T> |
14
+ * Concat<T> |
15
+ * readonly T[]
16
+ * } NotLazy
17
+ */
18
+
19
+ /**
20
+ * @template T
21
+ * @typedef {undefined | NonEmpty<T>} Result
22
+ */
23
+
24
+ /**
25
+ * @template T
26
+ * @typedef {() => List<T>} Thunk
27
+ */
28
+
29
+ /**
30
+ * @template T
31
+ * @typedef {{
32
+ * readonly isConcat?: undefined
33
+ * readonly first: T
34
+ * readonly tail: List<T>
35
+ * }} NonEmpty
36
+ */
37
+
38
+ /**
39
+ * @template T
40
+ * @typedef {{
41
+ * readonly isConcat: true
42
+ * readonly a: List<T>
43
+ * readonly b: List<T>
44
+ * }} Concat
45
+ */
46
+
47
+ /** @type {<T>(first: T) => (tail: List<T>) => NonEmpty<T>} */
48
+ const nonEmpty = first => tail => ({ first, tail })
49
+
50
+ /** @type {(i: number) => <T>(array: readonly T[]) => Result<T>} */
51
+ const fromArrayAt = i => array => i < array.length ? nonEmpty(array[i])(() => fromArrayAt(i + 1)(array)) : undefined
52
+
53
+ /** @type {<T>(array: readonly T[]) => Result<T>} */
54
+ const fromArray = fromArrayAt(0)
55
+
56
+ /** @type {<T>(a: List<T>) => (b: List<T>) => List<T>} */
57
+ const concat = a => b => b === undefined ? a : ({ isConcat: true, a, b })
58
+
59
+ /** @type {<T>(list: List<T>) => NotLazy<T> } */
60
+ const trampoline = list => {
61
+ let i = list
62
+ while (typeof i === 'function') { i = i() }
63
+ return i
64
+ }
65
+
66
+ /** @type {<T>(list: List<T>) => Result<T>} */
67
+ const next = list => {
68
+ /** @type {readonly[typeof list, typeof list]} */
69
+ let [a, b] = [list, undefined]
70
+ while (true) {
71
+ a = trampoline(a)
72
+
73
+ if (a instanceof Array) {
74
+ a = fromArray(a)
75
+ } else if (a?.isConcat) {
76
+ [a, b] = [a.a, concat(a.b)(b)]
77
+ continue
78
+ }
79
+
80
+ if (a !== undefined) {
81
+ return nonEmpty(a.first)(concat(a.tail)(b))
82
+ }
83
+
84
+ if (b === undefined) { return undefined }
85
+
86
+ [a, b] = [b, undefined]
87
+ }
88
+ }
89
+
90
+ /** @type {<T>(list: List<T>) => Iterable<T>} */
91
+ const iterable = list => ({
92
+ *[Symbol.iterator]() {
93
+ let i = list
94
+ while (true) {
95
+ const r = next(i)
96
+ if (r === undefined) { return }
97
+ yield r.first
98
+ i = r.tail
99
+ }
100
+ }
101
+ })
102
+
103
+ /** @type {<T>(list: List<T>) => readonly T[]} */
104
+ const toArray = list => {
105
+ const u = trampoline(list)
106
+ return u instanceof Array ? u : Array.from(iterable(u))
107
+ }
108
+
109
+ /** @type {<I, O>(step: (n: NonEmpty<I>) => List<O>) => (input: List<I>) => List<O>} */
110
+ const apply = f => input => () => {
111
+ const n = next(input)
112
+ if (n === undefined) { return undefined }
113
+ return f(n)
114
+ }
115
+
116
+ /** @type {<T>(n: NonEmpty<List<T>>) => List<T>} */
117
+ const flatStep = n => concat(n.first)(flat(n.tail))
118
+
119
+ /** @type {<T>(list: List<List<T>>) => List<T>} */
120
+ const flat = apply(flatStep)
121
+
122
+ /** @type {<I, O>(f: (value: I) => O) => (n: NonEmpty<I>) => List<O>} */
123
+ const mapStep = f => n => nonEmpty(f(n.first))(map(f)(n.tail))
124
+
125
+ /** @type {<I, O>(f: (value: I) => O) => (input: List<I>) => List<O>} */
126
+ const map = f => apply(mapStep(f))
127
+
128
+ /** @type {<I, O>(f: (value: I) => List<O>) => (input: List<I>) => List<O>} */
129
+ const flatMap = f => compose(map(f))(flat)
130
+
131
+ /** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
132
+ const filterStep = f => n => {
133
+ const tail = filter(f)(n.tail)
134
+ return f(n.first) ? nonEmpty(n.first)(tail) : tail
135
+ }
136
+
137
+ /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => List<T>} */
138
+ const filter = f => apply(filterStep(f))
139
+
140
+ /** @type {<I, O>(f: (value: I) => O|undefined) => (n: NonEmpty<I>) => List<O>} */
141
+ const filterMapStep = f => n => {
142
+ const [first, tail] = [f(n.first), filterMap(f)(n.tail)]
143
+ return first === undefined ? tail : nonEmpty(first)(tail)
144
+ }
145
+
146
+ /** @type {<I, O>(f: (value: I) => O|undefined) => (input: List<I>) => List<O>} */
147
+ const filterMap = f => apply(filterMapStep(f))
148
+
149
+ /** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
150
+ const takeWhileStep = f => n => f(n.first) ? nonEmpty(n.first)(takeWhile(f)(n.tail)) : undefined
151
+
152
+ /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => List<T>} */
153
+ const takeWhile = f => apply(takeWhileStep(f))
154
+
155
+ /** @type {(n: number) => <T>(result: NonEmpty<T>) => List<T>} */
156
+ const takeStep = n => ne => 0 < n ? nonEmpty(ne.first)(take(n - 1)(ne.tail)) : undefined
157
+
158
+ /** @type {(n: number) => <T>(input: List<T>) => List<T>} */
159
+ const take = n => apply(takeStep(n))
160
+
161
+ /** @type {<T>(f: (value: T) => boolean) => (ne: NonEmpty<T>) => List<T>} */
162
+ const dropWhileStep = f => ne => f(ne.first) ? dropWhile(f)(ne.tail) : ne
163
+
164
+ /** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => List<T>} */
165
+ const dropWhile = f => apply(dropWhileStep(f))
166
+
167
+ /** @type {(n: number) => <T>(ne: NonEmpty<T>) => List<T>} */
168
+ const dropStep = n => ne => 0 < n ? drop(n - 1)(ne.tail) : ne
169
+
170
+ /** @type {(n: number) => <T>(input: List<T>) => List<T>} */
171
+ const drop = n => apply(dropStep(n))
172
+
173
+ /** @type {<D>(def: D) => <T>(input: List<T>) => D|T} */
174
+ const first = def => input => {
175
+ const result = next(input)
176
+ if (result === undefined) { return def }
177
+ return result.first
178
+ }
179
+
180
+ /** @type {<D>(def: D) => <T>(input: List<T>) => D|T} */
181
+ const last = def => input => {
182
+ /** @typedef {typeof input extends List<infer T> ? T : never} T */
183
+ let i = nonEmpty(/** @type {(typeof def)|T} */(def))(input)
184
+ while (true) {
185
+ const result = next(i.tail)
186
+ if (result === undefined) {
187
+ return i.first
188
+ }
189
+ i = result
190
+ }
191
+ }
192
+
193
+ /** @type {<D>(def: D) => <T>(f: (value: T) => boolean) => (input: List<T>) => D|T} */
194
+ const find = def => f => input => first(def)(filter(f)(input))
195
+
196
+ /** @type {(input: List<boolean>) => boolean} */
197
+ const some = input => find
198
+ (false)
199
+ (/** @type {(_: boolean) => boolean} */(identity))
200
+ (input)
201
+
202
+ /** @type {(input: List<boolean>) => boolean} */
203
+ const every = input => !some(map(logicalNot)(input))
204
+
205
+ /** @type {<T>(value: T) => (sequence: List<T>) => boolean} */
206
+ const includes = value => input => some(map(strictEqual(value))(input))
207
+
208
+ /** @type {(count: number) => Thunk<number>} */
209
+ const countdown = count => () => {
210
+ if (count <= 0) { return undefined }
211
+ const first = count - 1
212
+ return nonEmpty(first)(countdown(first))
213
+ }
214
+
215
+ /** @type {<T>(list: List<T>) => List<T>} */
216
+ const cycle = list => () => {
217
+ const i = next(list)
218
+ return i === undefined ? undefined : nonEmpty(i.first)(concat(i.tail)(cycle(list)))
219
+ }
220
+
221
+ /** @type {<I, O>(op: operator.Scan<I, O>) => (ne: NonEmpty<I>) => List<O>} */
222
+ const scanStep = op => ne => {
223
+ const [o, newOp] = op(ne.first)
224
+ return nonEmpty(o)(scan(newOp)(ne.tail))
225
+ }
226
+
227
+ /** @type {<I, O>(op: operator.Scan<I, O>) => (input: List<I>) => List<O>} */
228
+ const scan = op => apply(scanStep(op))
229
+
230
+ /** @type {<I, S, O>(op: operator.StateScan<I, S, O>) => (init: S) => (input: List<I>) => List<O>} */
231
+ const stateScan = op => init => scan(stateScanToScan(op)(init))
232
+
233
+ /** @type {<I,O>(op: operator.Reduce<I, O>) => (init: O) => (input: List<I>) => List<O>} */
234
+ const reduceScan = op => init => scan(reduceToScan(op)(init))
235
+
236
+ /** @type {<I,O>(op: operator.Reduce<I, O>) => (init: O) => (input: List<I>) => O} */
237
+ const reduce = op => init => input => last(init)(reduceScan(op)(init)(input))
238
+
239
+ /** @type {<T>(op: operator.Fold<T>) => <D>(def: D) => (input: List<T>) => D|T} */
240
+ const fold = op => def => input => last(def)(scan(foldToScan(op))(input))
241
+
242
+ const sum = fold(operator.addition)(0)
243
+
244
+ const min = fold(operator.min)(undefined)
245
+
246
+ const max = fold(operator.max)(undefined)
247
+
248
+ /** @type {(separator: string) => (input: List<string>) => string} */
249
+ const join = separator => fold(operator.join(separator))('')
250
+
251
+ /** @type {<T>(input: List<T>) => number} */
252
+ const length = reduce(operator.counter)(0)
253
+
254
+ /**
255
+ * @template T
256
+ * @typedef {readonly[number, T]} Entry
257
+ */
258
+
259
+ /** @type {(index: number) => <T>(value: T) => readonly[Entry<T>, number]} */
260
+ const entryOperator = index => value => [[index, value], index + 1]
261
+
262
+ /** @type {<T>(input: List<T>) => List<Entry<T>>} */
263
+ const entries = (input) => {
264
+ /** @typedef {typeof input extends List<infer T> ? T : never} T */
265
+ return stateScan(/** @type {operator.StateScan<T, Number, Entry<T>>} */(entryOperator))(0)(input)
266
+ }
267
+
268
+ /** @type {<T>(prior: List<T>) => (value: T) => List<T>} */
269
+ const reverseOperator = prior => value => nonEmpty(value)(prior)
270
+
271
+ /** @type {<T>(input: List<T>) => List<T>} */
272
+ const reverse = reduce(reverseOperator)(undefined)
273
+
274
+ /** @type {<A>(a: A) => <B>(b: B) => readonly[A, B]} */
275
+ const tuple2 = a => b => [a, b]
276
+
277
+ /** @type {<A>(a: List<A>) => <B>(b: List<B>) => List<readonly[A, B]>} */
278
+ const zip = a => b => () => {
279
+ const aResult = next(a)
280
+ if (aResult === undefined) { return undefined }
281
+ const bResult = next(b)
282
+ if (bResult === undefined) { return undefined }
283
+ return nonEmpty(tuple2(aResult.first)(bResult.first))(zip(aResult.tail)(bResult.tail))
284
+ }
285
+
286
+ /** @type {<T>(e: operator.Equal<T>) => (a: List<T>) => (b: List<T>) => List<boolean>} */
287
+ const equalZip = e => a => b => () => {
288
+ const [aResult, bResult] = [next(a), next(b)]
289
+ return aResult === undefined || bResult === undefined
290
+ ? nonEmpty(aResult === bResult)(undefined)
291
+ : nonEmpty(e(aResult.first)(bResult.first))(equalZip(e)(aResult.tail)(bResult.tail))
292
+ }
293
+
294
+ /** @type {<T>(e: operator.Equal<T>) => (a: List<T>) => (b: List<T>) => boolean} */
295
+ const equal = e => a => b => every(equalZip(e)(a)(b))
296
+
297
+ module.exports = {
298
+ /** @readonly */
299
+ empty: undefined,
300
+ /** @readonly */
301
+ nonEmpty,
302
+ /** @readonly */
303
+ concat,
304
+ /** @readonly */
305
+ next,
306
+ /** @readonly */
307
+ iterable,
308
+ /** @readonly */
309
+ toArray,
310
+ /** @readonly */
311
+ flat,
312
+ /** @readonly */
313
+ map,
314
+ /** @readonly */
315
+ flatMap,
316
+ /** @readonly */
317
+ filter,
318
+ /** @readonly */
319
+ filterMap,
320
+ /** @readonly */
321
+ takeWhile,
322
+ /** @readonly */
323
+ take,
324
+ /** @readonly */
325
+ dropWhile,
326
+ /** @readonly */
327
+ drop,
328
+ /** @readonly */
329
+ first,
330
+ /** @readonly */
331
+ last,
332
+ /** @readonly */
333
+ find,
334
+ /** @readonly */
335
+ some,
336
+ /** @readonly */
337
+ every,
338
+ /** @readonly */
339
+ includes,
340
+ /** @readonly */
341
+ countdown,
342
+ /** @readonly */
343
+ cycle,
344
+ /** @readonly */
345
+ scan,
346
+ /** @readonly */
347
+ stateScan,
348
+ /** @readonly */
349
+ reduceScan,
350
+ /** @readonly */
351
+ reduce,
352
+ /** @readonly */
353
+ fold,
354
+ /** @readonly */
355
+ sum,
356
+ /** @readonly */
357
+ min,
358
+ /** @readonly */
359
+ max,
360
+ /** @readonly */
361
+ join,
362
+ /** @readonly */
363
+ length,
364
+ /** @readonly */
365
+ entries,
366
+ /** @readonly */
367
+ reverse,
368
+ /** @readonly */
369
+ zip,
370
+ /** @readonly */
371
+ equal,
372
+ }
@@ -1,11 +1,16 @@
1
1
  const _ = require('.')
2
2
  const json = require('../../json')
3
3
  const { sort } = require('../object')
4
- const { addition, strictEqual } = require('../function/operator')
4
+ const { addition, strictEqual, foldToScan } = require('../function/operator')
5
5
 
6
- /** @type {(sequence: _.Sequence<json.Unknown>) => string} */
6
+ /** @type {(sequence: _.List<json.Unknown>) => string} */
7
7
  const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
8
8
 
9
+ {
10
+ const x = stringify(_.toArray(_.take(10)(_.cycle([1, 2, 3]))))
11
+ if (x !== '[1,2,3,1,2,3,1,2,3,1]') { throw x }
12
+ }
13
+
9
14
  {
10
15
  const s = stringify([1, 2, 3])
11
16
  if (s !== '[1,2,3]') { throw s }
@@ -84,7 +89,7 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
84
89
  }
85
90
 
86
91
  {
87
- const op = _.scanState(addition)
92
+ const op = foldToScan(addition)
88
93
  const result = stringify(_.scan(op)([2, 3, 4, 5]))
89
94
  if (result !== '[2,5,9,14]') { throw result }
90
95
  }
@@ -130,7 +135,7 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
130
135
  }
131
136
 
132
137
  {
133
- const result = stringify(_.reverse([1,2,3,4,5]))
138
+ const result = stringify(_.reverse([1, 2, 3, 4, 5]))
134
139
  if (result !== '[5,4,3,2,1]') { throw result }
135
140
  }
136
141
 
@@ -146,7 +151,7 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
146
151
 
147
152
  {
148
153
  const result = _.some(_.map(x => x > 5)([0, 1, 7]))
149
- if (!result) { throw result}
154
+ if (!result) { throw result }
150
155
  }
151
156
 
152
157
  {
@@ -176,7 +181,7 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
176
181
 
177
182
  {
178
183
  const result = _.equal(strictEqual)([1])([2, 3])
179
- if (result) { throw result}
184
+ if (result) { throw result }
180
185
  }
181
186
 
182
187
  {
@@ -214,8 +219,8 @@ const stringify = sequence => json.stringify(sort)(_.toArray(sequence))
214
219
  const stress = () => {
215
220
 
216
221
  {
217
- // 100_000_000 is too much
218
- const n = 50_000_000
222
+ // 200_000_000 is too much
223
+ const n = 100_000_000
219
224
  const result = _.toArray(_.countdown(n))
220
225
  if (result.length !== n) { throw result.length }
221
226
  const len = _.length(_.filter(x => x > n)(result))
@@ -225,26 +230,30 @@ const stress = () => {
225
230
  console.log('first')
226
231
 
227
232
  {
228
- // 200_000_000 is too much
229
- const n = 100_000_000
233
+ // 100_000_000 is too much
234
+ const n = 50_000_000
230
235
  const result = _.toArray(_.countdown(n))
231
236
  if (result.length !== n) { throw result.length }
232
237
  const first = _.first(undefined)(result)
233
238
  if (first !== n - 1) { throw first }
234
239
  }
235
240
 
241
+ console.log('concat back')
242
+
236
243
  {
237
- /** @type {_.Sequence<number>} */
244
+ /** @type {_.List<number>} */
238
245
  let sequence = []
239
- // 10_000_000 is too much
240
- for (let i = 0; i < 5_000_000; ++i) {
246
+ // 20_000_000 is too much
247
+ for (let i = 0; i < 10_000_000; ++i) {
241
248
  sequence = _.concat(sequence)([i])
242
249
  }
243
250
  const r = _.toArray(sequence)
244
251
  }
245
252
 
253
+ console.log('flat to Array')
254
+
246
255
  {
247
- /** @type {_.Sequence<number>} */
256
+ /** @type {_.List<number>} */
248
257
  let sequence = []
249
258
  // 4_000_000 is too much
250
259
  for (let i = 0; i < 2_000_000; ++i) {
@@ -253,18 +262,22 @@ const stress = () => {
253
262
  const r = _.toArray(sequence)
254
263
  }
255
264
 
265
+ console.log('flat next')
266
+
256
267
  {
257
- /** @type {_.Sequence<number>} */
268
+ /** @type {_.List<number>} */
258
269
  let sequence = []
259
270
  // 5_000_000 is too much
260
- for (let i = 0; i < 2_000_000; ++i) {
271
+ for (let i = 0; i < 4_000_000; ++i) {
261
272
  sequence = _.flat([sequence, [i]])
262
273
  }
263
274
  const a = _.next(sequence)
264
275
  }
265
276
 
277
+ console.log('concat front')
278
+
266
279
  {
267
- /** @type {_.Sequence<number>} */
280
+ /** @type {_.List<number>} */
268
281
  let sequence = []
269
282
  // 20_000_000 is too much
270
283
  for (let i = 0; i < 10_000_000; ++i) {
@@ -274,7 +287,7 @@ const stress = () => {
274
287
  }
275
288
 
276
289
  {
277
- /** @type {_.Sequence<number>} */
290
+ /** @type {_.List<number>} */
278
291
  let sequence = []
279
292
  // 10_000_000 is too much
280
293
  for (let i = 0; i < 5_000_000; ++i) {
@@ -306,7 +319,7 @@ const stress = () => {
306
319
  }
307
320
  }
308
321
 
309
- // stress()
322
+ stress()
310
323
 
311
324
  module.exports = {
312
325
 
@@ -1,86 +1,80 @@
1
1
  const option = require("../option")
2
+ const btree = require('../btree')
2
3
  const { getVisitor, setVisitor, values } = require("../btree")
4
+ const compare = require("../function/compare")
3
5
  const { cmp } = require("../function/compare")
4
- const seq = require("../sequence")
6
+ const seq = require("../list")
5
7
 
6
- /** @typedef {import("../function/compare").Sign} Sign */
8
+ /** @typedef {compare.Sign} Sign */
7
9
 
8
10
  /**
9
11
  * @template T
10
- * @typedef {import("../btree").Leaf1<T>} Leaf1
12
+ * @typedef {btree.Leaf1<T>} Leaf1
11
13
  */
12
14
 
13
15
  /**
14
16
  * @template T
15
- * @typedef {import("../btree").Node<T>} TNode
17
+ * @typedef {btree.Node<T>} TNode
16
18
  */
17
19
 
18
20
  /**
19
21
  * @template T
20
- * @typedef {import("../function/compare").Compare<T>} Cmp
22
+ * @typedef {compare.Compare<T>} Cmp
21
23
  */
22
24
 
23
25
  /**
24
26
  * @template T
25
- * @typedef {readonly [string, T]} Entry
27
+ * @typedef {readonly[string, T]} Entry
26
28
  */
27
29
 
28
- /**
30
+ /**
29
31
  * @template T
30
- * @typedef {{
31
- * readonly get: (name: string) => T|undefined
32
- * readonly set: (name: string) => (value: T) => Map<T>
33
- * readonly entries: seq.Sequence<Entry<T>>
34
- * readonly root: undefined|TNode<Entry<T>>
35
- * }} Map
32
+ * @typedef {undefined|TNode<Entry<T>>} Map
36
33
  */
37
34
 
38
35
  /** @type {(a: string) => <T>(b: Entry<T>) => Sign} */
39
36
  const keyCmp = a => ([b]) => cmp(a)(b)
40
37
 
41
- /** @type {<T>(node: TNode<Entry<T>>) => Map<T>} */
42
- const create = root => ({
43
- get: name => option.map(([,value]) => value)(getVisitor(keyCmp(name))(root)),
44
- set: name => value => {
45
- const result = setVisitor(keyCmp(name))(() => [name, value])(root)
46
- switch (result[0]) {
47
- case 'replace': case 'overflow': { return create(result[1]) }
48
- default: { throw '' }
49
- }
50
- },
51
- entries: values(root),
52
- root,
53
- })
38
+ /** @type {(name: string) => <T>(map: Map<T>) => T|undefined} */
39
+ const at = name => map => {
40
+ if (map === undefined) { return undefined }
41
+ const result = getVisitor(keyCmp(name))(map)
42
+ return result === undefined ? undefined : result[1]
43
+ }
54
44
 
55
- /**
56
- * @type {{
57
- * readonly get: (name: string) => undefined
58
- * readonly set: (name: string) => <T>(value: T) => Map<T>
59
- * readonly entries: []
60
- * readonly root: undefined
61
- * }}
62
- */
63
- const empty = {
64
- get: () => undefined,
65
- set: name => value => create([[name, value]]),
66
- entries: [],
67
- root: undefined
45
+ /** @type {(name: string) => <T>(value: T) => (map: Map<T>) => Map<T>} */
46
+ const set = name => value => map => {
47
+ /** @type {Entry<typeof value>} */
48
+ const entry = [name, value]
49
+ if (map === undefined) { return [entry] }
50
+ const result = setVisitor(keyCmp(name))(() => entry)(map)
51
+ switch (result[0]) {
52
+ case 'replace': case 'overflow': { return result[1] }
53
+ default: { throw 'invalid BTree operation' }
54
+ }
68
55
  }
69
56
 
57
+ /** @type {<T>(map: Map<T>) => seq.List<Entry<T>>} */
58
+ const entries = map => map === undefined ? [] : values(map)
59
+
70
60
  /** @type {<T>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
71
- const setOperator = map => ([k, v]) => map.set(k)(v)
61
+ const setOp = map => ([name, value]) => set(name)(value)(map)
72
62
 
73
- /** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
63
+ /** @type {<T>(entries: seq.List<Entry<T>>) => Map<T>} */
74
64
  const fromEntries = entries => {
75
- /** @typedef {typeof entries extends seq.Sequence<Entry<infer T>> ? T : never} T */
76
- /** @type {Map<T>} */
77
- const init = empty
78
- return seq.reduce(setOperator)(init)(entries)
65
+ /** @typedef {typeof entries extends seq.List<Entry<infer T>> ? T : never} T */
66
+ return seq.reduce(setOp)(/** @type {Map<T>} */(undefined))(entries)
79
67
  }
80
68
 
81
69
  module.exports = {
82
70
  /** @readonly */
83
- empty,
71
+ empty: undefined,
72
+ /** @readonly */
73
+ at,
74
+ /** @readonly */
75
+ set,
76
+ /** @readonly */
77
+ entries,
84
78
  /** @readonly */
85
79
  fromEntries,
86
80
  }