functionalscript 0.0.239 → 0.0.243

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.
@@ -1,6 +1,6 @@
1
1
  const cmp = require('../function/compare')
2
2
  const { index3, index5 } = cmp
3
- const seq = require('../sequence')
3
+ const seq = require('../list')
4
4
 
5
5
  /**
6
6
  * @template T
@@ -129,41 +129,39 @@ const seq = require('../sequence')
129
129
  const split = ([n0, v1, n2, v3, n4, v5, n6]) => [[n0, v1, n2], v3, [n4, v5, n6]]
130
130
 
131
131
  /**
132
- * @type {<T>(overflow: (o: Branch3<T>) => Result<T>) =>
132
+ * @type {<T>(extend: (o: Branch3<T>) => Result<T>) =>
133
133
  * (replace: (r: Node<T>) => Node<T>) =>
134
134
  * (result: Result<T>) =>
135
135
  * Result<T>}
136
136
  */
137
- const merge = overflow => replace => result => {
137
+ const merge = extend => replace => result => {
138
138
  switch (result[0]) {
139
139
  case 'done': { return result }
140
140
  case 'replace': { return ['replace', replace(result[1])] }
141
- default: { return overflow(result[1]) }
141
+ default: { return extend(result[1]) }
142
142
  }
143
143
  }
144
144
 
145
- /**
146
- * @type {<T>(overflow: (o: Branch3<T>) => Branch5<T>) =>
147
- * (replace: (r: Node<T>) => Branch3<T>) =>
148
- * (result: Result<T>) =>
149
- * Result<T>}
150
- */
151
- const merge2 = overflow => merge(o => ['replace', overflow(o)])
152
-
153
- /**
154
- * @type {<T>(overflow: (o: Branch3<T>) => Branch7<T>) =>
155
- * (replace: (r: Node<T>) => Branch5<T>) =>
156
- * (result: Result<T>) =>
157
- * Result<T>}
158
- */
159
- const merge3 = overflow => merge(o => ['overflow', split(overflow(o))])
160
-
161
145
  /** @type {(visitor: Visitor) => <T>(cmp: Cmp<T>) => (init: Lazy<T>) => (node: Node<T>) => Result<T>} */
162
146
  const visit = ({ found, notFound }) => cmp => {
163
147
  const i3 = index3(cmp)
164
148
  const i5 = index5(cmp)
149
+ /** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T */
150
+ /**
151
+ * @type {(extend: (o: Branch3<T>) => Branch5<T>) =>
152
+ * (replace: (r: Node<T>) => Branch3<T>) =>
153
+ * (result: Result<T>) =>
154
+ * Result<T>}
155
+ */
156
+ const merge2 = extend => merge(o => ['replace', extend(o)])
157
+ /**
158
+ * @type {(extend: (o: Branch3<T>) => Branch7<T>) =>
159
+ * (replace: (r: Node<T>) => Branch5<T>) =>
160
+ * (result: Result<T>) =>
161
+ * Result<T>}
162
+ */
163
+ const merge3 = extend => merge(o => ['overflow', split(extend(o))])
165
164
  return init => {
166
- /** @typedef {typeof cmp extends Cmp<infer T> ? T : never} T*/
167
165
  /** @type {(node: Node<T>) => Result<T>} */
168
166
  const f = node => {
169
167
  switch (node.length) {
@@ -188,14 +186,14 @@ const visit = ({ found, notFound }) => cmp => {
188
186
  switch (i3(v1)) {
189
187
  case 0: {
190
188
  return merge2
191
- (o => [...o, v1, n2])
189
+ (e => [...e, v1, n2])
192
190
  (r => [r, v1, n2])
193
191
  (f(n0))
194
192
  }
195
193
  case 1: { return found.branch3(init)(node) }
196
194
  default: {
197
195
  return merge2
198
- (o => [n0, v1, ...o])
196
+ (e => [n0, v1, ...e])
199
197
  (r => [n0, v1, r])
200
198
  (f(n2))
201
199
  }
@@ -305,7 +303,7 @@ const replaceVisitor = {
305
303
  notFound: notFoundGet,
306
304
  }
307
305
 
308
- /** @type {<T>(node: Node<T>) => seq.Sequence<T>} */
306
+ /** @type {<T>(node: Node<T>) => seq.List<T>} */
309
307
  const values = node => () => {
310
308
  const f = () => {
311
309
  switch (node.length) {
@@ -339,7 +337,7 @@ module.exports = {
339
337
  * @type { <T>(cmp: Cmp<T>) => (node: Node<T>) => T|undefined }
340
338
  */
341
339
  getVisitor: cmp => node => {
342
- const result = visit(getVisitor)(cmp)(() => { throw '' })(node)
340
+ const result = visit(getVisitor)(cmp)(() => { throw 'getVisitor' })(node)
343
341
  if (result[0] === 'done') { return result[1] }
344
342
  return undefined
345
343
  },
@@ -1,7 +1,7 @@
1
1
  const btree = require('.')
2
2
  const { setVisitor, values } = btree
3
3
  const { cmp } = require('../function/compare')
4
- const list = require('../sequence')
4
+ const list = require('../list')
5
5
 
6
6
  /** @type {(node: btree.Node<string>) => (value: string) => btree.Node<string>} */
7
7
  const set = node => value => {
@@ -22,7 +22,7 @@ const test = () => {
22
22
  _map = set(_map)('f')
23
23
  //
24
24
  {
25
- /** @type {import('../sequence').Result<string>} */
25
+ /** @type {list.Result<string>} */
26
26
  let _item = list.next(values(_map))
27
27
  while (_item !== undefined) {
28
28
  _item = list.next(_item.tail)
@@ -2,44 +2,76 @@
2
2
  * @template A
3
3
  * @template B
4
4
  * @template R
5
- * @typedef {(a: A) => (b: B) => R} BinaryOperator
5
+ * @typedef {(a: A) => (b: B) => R} Binary
6
6
  */
7
7
 
8
8
  /**
9
- * @template R
10
- * @template T
11
- * @typedef {BinaryOperator<R, T, R>} ReduceOperator
9
+ * @template I,O
10
+ * @typedef {Binary<O, I, O>} Reduce
12
11
  */
13
12
 
14
- /** @type {(separator: string) => ReduceOperator<string, string>} */
13
+ /** @type {(separator: string) => Fold<string>} */
15
14
  const join = separator => prior => value => `${prior}${separator}${value}`
16
15
 
17
- /** @type {(sum: number) => (value: number) => number} */
16
+ /** @type {Fold<number>} */
18
17
  const addition = a => b => a + b
19
18
 
20
19
  /**
21
20
  * @template T
22
21
  * @template R
23
- * @typedef {(value: T) => R} UnaryOperator
22
+ * @typedef {(value: T) => R} Unary
24
23
  */
25
24
 
26
- /** @type {(value: boolean) => boolean} */
25
+ /** @type {Unary<boolean, boolean>} */
27
26
  const logicalNot = v => !v
28
27
 
29
28
  /**
30
29
  * @template T
31
- * @typedef {(a: T) => (b: T) => boolean} EqualOperator
30
+ * @typedef {Binary<T, T, boolean>} Equal
32
31
  */
33
32
 
34
33
  /** @type {<T>(a: T) => (b: T) => boolean} */
35
34
  const strictEqual = a => b => a === b
36
35
 
37
- /** @type {ReduceOperator<number, number>} */
36
+ /** @type {Fold<number>} */
38
37
  const min = a => b => a < b ? a : b
39
38
 
40
- /** @type {ReduceOperator<number, number>} */
39
+ /** @type {Fold<number>} */
41
40
  const max = a => b => a > b ? a : b
42
41
 
42
+ /**
43
+ * @template I,O
44
+ * @typedef {(input: I) => readonly[O, Scan<I,O>]} Scan
45
+ */
46
+
47
+ /**
48
+ * @template I,S,O
49
+ * @typedef {(prior: S) => (input: I) => readonly[O, S]} StateScan
50
+ */
51
+
52
+ /** @type {<I, S, O>(op: StateScan<I, S, O>) => (prior: S) => Scan<I, O>} */
53
+ const stateScanToScan = op => prior => i => {
54
+ const [o, s] = op(prior)(i)
55
+ return [o, stateScanToScan(op)(s)]
56
+ }
57
+
58
+ /** @type {<I, O>(reduce: Reduce<I, O>) => (prior: O) => Scan<I, O>} */
59
+ const reduceToScan = reduce => prior => i => {
60
+ const result = reduce(prior)(i)
61
+ return [result, reduceToScan(reduce)(result)]
62
+ }
63
+
64
+ /**
65
+ * @template T
66
+ * @typedef {Reduce<T, T>} Fold
67
+ */
68
+
69
+ /** @type {<T>(fold: Fold<T>) => Scan<T, T>} */
70
+ const foldToScan = op => init => [init, reduceToScan(op)(init)]
71
+
72
+ /** @type {(a: number) => () => number} */
73
+ const counter = a => () => a + 1
74
+
43
75
  module.exports = {
44
76
  /** @readonly */
45
77
  join,
@@ -53,4 +85,12 @@ module.exports = {
53
85
  min,
54
86
  /** @readonly */
55
87
  max,
88
+ /** @readonly */
89
+ stateScanToScan,
90
+ /** @readonly */
91
+ reduceToScan,
92
+ /** @readonly */
93
+ foldToScan,
94
+ /** @readonly */
95
+ counter,
56
96
  }
@@ -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
+ }