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