functionalscript 0.0.488 → 0.0.490
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/.github/workflows/deno.yml +1 -1
- package/README.md +4 -2
- package/dev/test/module.f.cjs +44 -21
- package/dev/test.mjs +11 -5
- package/package.json +1 -1
- package/types/array/module.f.cjs +3 -6
- package/types/array/test.f.cjs +1 -2
- package/types/byte_set/module.f.cjs +7 -8
- package/types/list/module.f.cjs +27 -31
- package/types/map/module.f.cjs +2 -1
- package/types/nullable/test.f.cjs +2 -2
- package/types/sorted_list/module.f.cjs +2 -3
- package/types/sorted_set/module.f.cjs +3 -3
package/README.md
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
FunctionalScript is a purely functional programming language and a strict subset of
|
|
4
4
|
[ECMAScript](https://en.wikipedia.org/wiki/ECMAScript)/[JavaScript](https://en.wikipedia.org/wiki/JavaScript). It's inspired by
|
|
5
5
|
|
|
6
|
-
- [JSON](https://en.wikipedia.org/wiki/JSON)
|
|
7
|
-
|
|
6
|
+
- [JSON](https://en.wikipedia.org/wiki/JSON) and [JSON5](https://json5.org/) as subsets of JavaScript.
|
|
7
|
+
JSON is also a subset of FunctionalScript.
|
|
8
|
+
- [asm.JS](https://en.wikipedia.org/wiki/Asm.js)/[WebAssembly](https://en.wikipedia.org/wiki/WebAssembly),
|
|
9
|
+
as a subset of JavaScript.
|
|
8
10
|
- [TypeScript](https://en.wikipedia.org/wiki/TypeScript), as a superset of JavaScript.
|
|
9
11
|
|
|
10
12
|
[A brief description of FunctionalScript Programming Language](./doc/LANGUAGE.md).
|
package/dev/test/module.f.cjs
CHANGED
|
@@ -26,11 +26,17 @@ const { reset, fgGreen } = require('../../text/sgr/module.f.cjs')
|
|
|
26
26
|
* @typedef {(v: string) => (state: T) => T} Log
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* @template T
|
|
31
|
+
* @typedef {(state: T) => readonly[number, T]} PerformanceNow
|
|
32
|
+
*/
|
|
33
|
+
|
|
29
34
|
/**
|
|
30
35
|
* @template T
|
|
31
36
|
* @typedef {{
|
|
32
37
|
* readonly moduleMap: ModuleMap,
|
|
33
38
|
* readonly log: Log<T>,
|
|
39
|
+
* readonly performanceNow: PerformanceNow<T>,
|
|
34
40
|
* readonly state: T,
|
|
35
41
|
* }} Input
|
|
36
42
|
*/
|
|
@@ -38,49 +44,66 @@ const { reset, fgGreen } = require('../../text/sgr/module.f.cjs')
|
|
|
38
44
|
/** @type {(s: string) => boolean} */
|
|
39
45
|
const isTest = s => s.endsWith('test.f.cjs')
|
|
40
46
|
|
|
47
|
+
/**
|
|
48
|
+
* @template T
|
|
49
|
+
* @typedef {readonly[number, T]} State
|
|
50
|
+
*/
|
|
51
|
+
|
|
41
52
|
/** @type {<T>(input: Input<T>) => T} */
|
|
42
|
-
const main =
|
|
43
|
-
|
|
44
|
-
/** @
|
|
45
|
-
|
|
53
|
+
const main = input => {
|
|
54
|
+
let { moduleMap, log, performanceNow, state } = input
|
|
55
|
+
/** @typedef {input extends Input<infer T> ? T : never} T */
|
|
56
|
+
/** @type {(i: string) => (v: unknown) => (state: State<T>) => State<T>} */
|
|
57
|
+
const test = i => v => ([time, state]) => {
|
|
46
58
|
const next = test(`${i}| `)
|
|
47
59
|
switch (typeof v) {
|
|
48
60
|
case 'function': {
|
|
49
61
|
if (v.length === 0) {
|
|
62
|
+
let b = 0;
|
|
63
|
+
[b, state] = performanceNow(state)
|
|
50
64
|
const r = v()
|
|
51
|
-
|
|
52
|
-
state =
|
|
65
|
+
let e = 0;
|
|
66
|
+
[e, state] = performanceNow(state)
|
|
67
|
+
const delta = e - b
|
|
68
|
+
time += delta
|
|
69
|
+
state = log(`${i}() ${fgGreen}ok${reset}, ${delta} ms`)(state);
|
|
70
|
+
[time, state] = next(r)([time, state])
|
|
53
71
|
}
|
|
54
72
|
break
|
|
55
73
|
}
|
|
56
74
|
case 'object': {
|
|
57
|
-
/** @type {(k: readonly[string|number, unknown]) => (state: T) => T} */
|
|
58
|
-
const f = ([k, v]) => state => {
|
|
59
|
-
state = log(`${i}${k}:`)(state)
|
|
60
|
-
state = next(v)(state)
|
|
61
|
-
return state
|
|
75
|
+
/** @type {(k: readonly[string|number, unknown]) => (state: State<T>) => State<T>} */
|
|
76
|
+
const f = ([k, v]) => ([time, state]) => {
|
|
77
|
+
state = log(`${i}${k}:`)(state);
|
|
78
|
+
[time, state] = next(v)([time, state])
|
|
79
|
+
return [time, state]
|
|
62
80
|
}
|
|
63
|
-
const foldF = fold(f)(state)
|
|
81
|
+
const foldF = fold(f)([time, state])
|
|
64
82
|
if (v instanceof Array) {
|
|
65
|
-
state = foldF(list.entries(v))
|
|
83
|
+
[time, state] = foldF(list.entries(v))
|
|
66
84
|
} else if (v !== null) {
|
|
67
|
-
state = foldF(Object.entries(v))
|
|
85
|
+
[time, state] = foldF(Object.entries(v))
|
|
68
86
|
}
|
|
69
87
|
break
|
|
70
88
|
}
|
|
71
89
|
}
|
|
72
|
-
return state
|
|
90
|
+
return [time, state]
|
|
73
91
|
}
|
|
74
92
|
const next = test('| ')
|
|
75
|
-
/** @type {(k: readonly[string, Module]) => (
|
|
76
|
-
const f = ([k, v]) => state => {
|
|
93
|
+
/** @type {(k: readonly[string, Module]) => (fs: State<T>) => State<T>} */
|
|
94
|
+
const f = ([k, v]) => ([time, state]) => {
|
|
77
95
|
if (isTest(k)) {
|
|
78
|
-
state = log(`testing ${k}`)(state)
|
|
79
|
-
state = next(v.exports)(state)
|
|
96
|
+
state = log(`testing ${k}`)(state);
|
|
97
|
+
[time, state] = next(v.exports)([time, state])
|
|
80
98
|
}
|
|
81
|
-
return state
|
|
99
|
+
return [time, state]
|
|
82
100
|
}
|
|
83
|
-
|
|
101
|
+
/** @type {State<T>} */
|
|
102
|
+
const init = [0, state]
|
|
103
|
+
let time = 0;
|
|
104
|
+
[time, state] = fold(f)(init)(Object.entries(moduleMap))
|
|
105
|
+
state = log(`total ${time} ms`)(state);
|
|
106
|
+
return state
|
|
84
107
|
}
|
|
85
108
|
|
|
86
109
|
module.exports = main
|
package/dev/test.mjs
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
import { loadModuleMap } from './module.mjs'
|
|
2
2
|
|
|
3
|
+
/** @type {(s: string) => <T>(_: T) => T} */
|
|
4
|
+
const log = s => state => {
|
|
5
|
+
console.log(s)
|
|
6
|
+
return state
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** @type {<T>(_: T) => readonly[number, T]} */
|
|
10
|
+
const performanceNow = state => [performance.now(), state]
|
|
11
|
+
|
|
3
12
|
// test runner.
|
|
4
13
|
const main = async() => {
|
|
5
14
|
const moduleMap = await loadModuleMap()
|
|
6
15
|
|
|
7
|
-
|
|
8
|
-
const log = s => state => {
|
|
9
|
-
console.log(s)
|
|
10
|
-
return state
|
|
11
|
-
}
|
|
16
|
+
// await import(self.Deno ? 'https://deno.land/std/node/fs/promises.ts' : 'node:fs/promises')
|
|
12
17
|
|
|
13
18
|
/** @type {any} */
|
|
14
19
|
const f = moduleMap['./dev/test/module.f.cjs'].exports
|
|
15
20
|
f({
|
|
16
21
|
moduleMap,
|
|
17
22
|
log,
|
|
23
|
+
performanceNow,
|
|
18
24
|
})
|
|
19
25
|
}
|
|
20
26
|
|
package/package.json
CHANGED
package/types/array/module.f.cjs
CHANGED
|
@@ -85,16 +85,16 @@ const uncheckTail = a => a.slice(1)
|
|
|
85
85
|
const uncheckHead = a => a.slice(0, -1)
|
|
86
86
|
|
|
87
87
|
/** @type {(index: number) => <T>(a: readonly T[]) => T|null} */
|
|
88
|
-
const
|
|
88
|
+
const at = i => a => {
|
|
89
89
|
const r = a[i]
|
|
90
90
|
return r === void 0 ? null : r
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
/** @type {<T>(_: readonly T[]) => T|null} */
|
|
94
|
-
const first =
|
|
94
|
+
const first = at(0)
|
|
95
95
|
|
|
96
96
|
/** @type {<T>(_: readonly T[]) => T|null} */
|
|
97
|
-
const last = a =>
|
|
97
|
+
const last = a => at(a.length - 1)(a)
|
|
98
98
|
|
|
99
99
|
/** @type {<T>(_: readonly T[]) => readonly T[] | null} */
|
|
100
100
|
const tail = a => a.length === 0 ? null : uncheckTail(a)
|
|
@@ -117,9 +117,6 @@ const splitLast = a => {
|
|
|
117
117
|
return [uncheckHead(a), lastA]
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
/** @type {(index: number) => <T>(a: readonly T[]) => readonly[T]|null} */
|
|
121
|
-
const at = index => a => index < a.length ? [a[index]] : null
|
|
122
|
-
|
|
123
120
|
module.exports = {
|
|
124
121
|
/** @readonly */
|
|
125
122
|
at,
|
package/types/array/test.f.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { fn } = require('../function/module.f.cjs')
|
|
1
|
+
const { fn, compose } = require('../function/module.f.cjs')
|
|
2
2
|
const rangeMap = require('../range_map/module.f.cjs')
|
|
3
3
|
const sortedSet = require('../sorted_set/module.f.cjs')
|
|
4
4
|
const list = require('../list/module.f.cjs')
|
|
@@ -31,17 +31,17 @@ const union = a => b => a | b
|
|
|
31
31
|
/** @type {(a: ByteSet) => (b: ByteSet) => ByteSet} */
|
|
32
32
|
const intersect = a => b => a & b
|
|
33
33
|
|
|
34
|
-
/** @type {(a: ByteSet) => (b: ByteSet) => ByteSet} */
|
|
35
|
-
const difference = a => b => intersect(a)(complement(b))
|
|
36
|
-
|
|
37
34
|
/** @type {(n: ByteSet) => ByteSet} */
|
|
38
35
|
const complement = n => universe ^ n
|
|
39
36
|
|
|
37
|
+
/** @type {(a: ByteSet) => (b: ByteSet) => ByteSet} */
|
|
38
|
+
const difference = compose(intersect)(compose(complement))
|
|
39
|
+
|
|
40
40
|
// additional operations
|
|
41
41
|
|
|
42
|
-
const set =
|
|
42
|
+
const set = compose(one)(union)
|
|
43
43
|
|
|
44
|
-
const setRange =
|
|
44
|
+
const setRange = compose(range)(union)
|
|
45
45
|
|
|
46
46
|
/** @type {(n: Byte) => (s: ByteSet) => ByteSet} */
|
|
47
47
|
const unset = n => s => difference(s)(one(n))
|
|
@@ -49,8 +49,7 @@ const unset = n => s => difference(s)(one(n))
|
|
|
49
49
|
const counter = reverse(countdown(256))
|
|
50
50
|
|
|
51
51
|
/** @type {(n: ByteSet) => (s: string) => (i: number) => rangeMap.RangeMap<sortedSet.SortedSet<string>>} */
|
|
52
|
-
const toRangeMapOp = n => s => i =>
|
|
53
|
-
{
|
|
52
|
+
const toRangeMapOp = n => s => i => {
|
|
54
53
|
const current = has(i + 1)(n)
|
|
55
54
|
const prev = has(i)(n)
|
|
56
55
|
if (current === prev) { return null }
|
package/types/list/module.f.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
const
|
|
1
|
+
const function_ = require('../function/module.f.cjs')
|
|
2
|
+
const { identity, fn, compose } = function_
|
|
2
3
|
const operator = require('../function/operator/module.f.cjs')
|
|
3
4
|
const {
|
|
4
5
|
counter,
|
|
@@ -121,13 +122,13 @@ const apply = f => input => () => {
|
|
|
121
122
|
}
|
|
122
123
|
|
|
123
124
|
/** @type {<T>(n: NonEmpty<List<T>>) => List<T>} */
|
|
124
|
-
const flatStep =
|
|
125
|
+
const flatStep = ({ first, tail }) => concat(first)(flat(tail))
|
|
125
126
|
|
|
126
127
|
/** @type {<T>(list: List<List<T>>) => Thunk<T>} */
|
|
127
128
|
const flat = apply(flatStep)
|
|
128
129
|
|
|
129
130
|
/** @type {<I, O>(f: (value: I) => O) => (n: NonEmpty<I>) => List<O>} */
|
|
130
|
-
const mapStep = f =>
|
|
131
|
+
const mapStep = f => ({ first, tail }) => ({ first: f(first), tail: map(f)(tail) })
|
|
131
132
|
|
|
132
133
|
/** @type {<I, O>(f: (value: I) => O) => (input: List<I>) => Thunk<O>} */
|
|
133
134
|
const map = f => apply(mapStep(f))
|
|
@@ -136,9 +137,9 @@ const map = f => apply(mapStep(f))
|
|
|
136
137
|
const flatMap = f => compose(map(f))(flat)
|
|
137
138
|
|
|
138
139
|
/** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
|
|
139
|
-
const filterStep = f =>
|
|
140
|
-
const
|
|
141
|
-
return f(
|
|
140
|
+
const filterStep = f => ({ first, tail }) => {
|
|
141
|
+
const newTail = filter(f)(tail)
|
|
142
|
+
return f(first) ? { first, tail: newTail } : newTail
|
|
142
143
|
}
|
|
143
144
|
|
|
144
145
|
/** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => Thunk<T>} */
|
|
@@ -154,13 +155,13 @@ const filterMapStep = f => n => {
|
|
|
154
155
|
const filterMap = f => apply(filterMapStep(f))
|
|
155
156
|
|
|
156
157
|
/** @type {<T>(f: (value: T) => boolean) => (n: NonEmpty<T>) => List<T>} */
|
|
157
|
-
const takeWhileStep = f =>
|
|
158
|
+
const takeWhileStep = f => ({ first, tail }) => f(first) ? { first, tail: takeWhile(f)(tail) } : null
|
|
158
159
|
|
|
159
160
|
/** @type {<T>(f: (value: T) => boolean) => (input: List<T>) => Thunk<T>} */
|
|
160
161
|
const takeWhile = f => apply(takeWhileStep(f))
|
|
161
162
|
|
|
162
163
|
/** @type {(n: number) => <T>(result: NonEmpty<T>) => List<T>} */
|
|
163
|
-
const takeStep = n =>
|
|
164
|
+
const takeStep = n => ({ first, tail }) => 0 < n ? { first: first, tail: take(n - 1)(tail) } : null
|
|
164
165
|
|
|
165
166
|
/** @type {(n: number) => <T>(input: List<T>) => Thunk<T>} */
|
|
166
167
|
const take = n => apply(takeStep(n))
|
|
@@ -179,8 +180,8 @@ const drop = n => apply(dropStep(n))
|
|
|
179
180
|
|
|
180
181
|
/** @type {<D>(def: D) => <T>(input: List<T>) => D|T} */
|
|
181
182
|
const first = def => input => {
|
|
182
|
-
const
|
|
183
|
-
return
|
|
183
|
+
const ne = next(input)
|
|
184
|
+
return ne === null ? def : ne.first
|
|
184
185
|
}
|
|
185
186
|
|
|
186
187
|
/** @type {<D>(first: D) => <T>(tail: List<T>) => D|T} */
|
|
@@ -198,28 +199,24 @@ const last = first => tail => {
|
|
|
198
199
|
}
|
|
199
200
|
|
|
200
201
|
/** @type {<D>(def: D) => <T>(f: (value: T) => boolean) => (input: List<T>) => D|T} */
|
|
201
|
-
const find = def => f =>
|
|
202
|
-
|
|
203
|
-
const findTrue = find(false)
|
|
202
|
+
const find = def => f => compose(filter(f))(first(def))
|
|
204
203
|
|
|
205
204
|
/** @type {(input: List<boolean>) => boolean} */
|
|
206
|
-
const some =
|
|
207
|
-
(/** @type {(_: boolean) => boolean} */(identity))
|
|
208
|
-
(input)
|
|
209
|
-
|
|
210
|
-
/** @type {<T>(f: List<T>) => Thunk<boolean>} */
|
|
211
|
-
const mapTrue = map(() => true)
|
|
205
|
+
const some = find(false)(identity)
|
|
212
206
|
|
|
213
207
|
/** @type {<T>(input: List<T>) => boolean} */
|
|
214
|
-
const isEmpty =
|
|
208
|
+
const isEmpty = fn(map(() => true))
|
|
209
|
+
.then(some)
|
|
210
|
+
.then(logicalNot)
|
|
211
|
+
.result
|
|
215
212
|
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
213
|
+
const every = fn(map(logicalNot))
|
|
214
|
+
.then(some)
|
|
215
|
+
.then(logicalNot)
|
|
216
|
+
.result
|
|
220
217
|
|
|
221
218
|
/** @type {<T>(value: T) => (sequence: List<T>) => boolean} */
|
|
222
|
-
const includes = value =>
|
|
219
|
+
const includes = value => compose(map(strictEqual(value)))(some)
|
|
223
220
|
|
|
224
221
|
/** @type {(count: number) => Thunk<number>} */
|
|
225
222
|
const countdown = count => () => {
|
|
@@ -229,7 +226,7 @@ const countdown = count => () => {
|
|
|
229
226
|
}
|
|
230
227
|
|
|
231
228
|
/** @type {<T>(v: T) => (c: number) => Thunk<T>} */
|
|
232
|
-
const repeat = v =>
|
|
229
|
+
const repeat = v => compose(countdown)(map(() => v))
|
|
233
230
|
|
|
234
231
|
/** @type {<T>(list: List<T>) => List<T>} */
|
|
235
232
|
const cycle = list => () => {
|
|
@@ -247,17 +244,16 @@ const scanStep = op => ne => {
|
|
|
247
244
|
const scan = op => apply(scanStep(op))
|
|
248
245
|
|
|
249
246
|
/** @type {<I, S, O>(op: operator.StateScan<I, S, O>) => (init: S) => (input: List<I>) => Thunk<O>} */
|
|
250
|
-
const stateScan = op =>
|
|
247
|
+
const stateScan = op => compose(stateScanToScan(op))(scan)
|
|
251
248
|
|
|
252
249
|
/** @type {<I,O>(op: operator.Fold<I, O>) => (init: O) => (input: List<I>) => Thunk<O>} */
|
|
253
|
-
const foldScan = op =>
|
|
250
|
+
const foldScan = op => compose(foldToScan(op))(scan)
|
|
254
251
|
|
|
255
252
|
/** @type {<I,O>(op: operator.Fold<I, O>) => (init: O) => (input: List<I>) => O} */
|
|
256
|
-
const fold = op => init =>
|
|
253
|
+
const fold = op => init => compose(foldScan(op)(init))(last(init))
|
|
257
254
|
|
|
258
255
|
/** @type {<T>(op: operator.Reduce<T>) => <D>(def: D) => (input: List<T>) => D|T} */
|
|
259
|
-
const reduce = op => def =>
|
|
260
|
-
|
|
256
|
+
const reduce = op => def => compose(scan(reduceToScan(op)))(last(def))
|
|
261
257
|
|
|
262
258
|
/** @type {<T>(input: List<T>) => number} */
|
|
263
259
|
const length = fold(counter)(0)
|
package/types/map/module.f.cjs
CHANGED
|
@@ -39,7 +39,8 @@ const at = name => map => {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/** @type {<T>(reduce: operator.Reduce<T>) => (entry: Entry<T>) => (map: Map<T>) => Map<T>} */
|
|
42
|
-
const setReduceEntry = reduce => entry =>
|
|
42
|
+
const setReduceEntry = reduce => entry =>
|
|
43
|
+
set(keyCmp(entry[0]))(old => old === null ? entry : [old[0], reduce(old[1])(entry[1])])
|
|
43
44
|
|
|
44
45
|
/** @type {<T>(reduce: operator.Reduce<T>) => (name: string) => (value: T) => (map: Map<T>) => Map<T>} */
|
|
45
46
|
const setReduce = reduce => name => value => setReduceEntry(reduce)([name, value])
|
|
@@ -4,6 +4,6 @@ module.exports = () => {
|
|
|
4
4
|
const optionSq = _.map(v => v * v)
|
|
5
5
|
const sq3 = optionSq(3)
|
|
6
6
|
if (sq3 !== 9) { throw sq3 }
|
|
7
|
-
const
|
|
8
|
-
if (
|
|
7
|
+
const sqNull = optionSq(null)
|
|
8
|
+
if (sqNull !== null) { throw sqNull }
|
|
9
9
|
}
|
|
@@ -41,9 +41,8 @@ const { identity } = require('../function/module.f.cjs')
|
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
43
|
/** @type {<T,S>(reduce: MergeReduce<T,S>) => (state: S) => (a: list.List<T>) => (b: list.List<T>) => list.List<T>} */
|
|
44
|
-
const genericMerge =
|
|
45
|
-
|
|
46
|
-
/** @typedef {typeof reduce extends MergeReduce<infer T, infer S> ? [T, S] : never} TS */
|
|
44
|
+
const genericMerge = ({ reduceOp, tailReduce }) => {
|
|
45
|
+
/** @typedef {typeof reduceOp extends ReduceOp<infer T, infer S> ? [T, S] : never} TS */
|
|
47
46
|
/** @typedef {TS[0]} T */
|
|
48
47
|
/** @typedef {TS[1]} S */
|
|
49
48
|
/** @type {(state: S) => (a: list.List<T>) => (b: list.List<T>) => list.List<T>} */
|
|
@@ -21,8 +21,10 @@ const union = cmp => a => b => toArray(merge(cmp)(a)(b))
|
|
|
21
21
|
/** @type {<T>(cmp: Cmp<T>) => (a: SortedSet<T>) => (b: SortedSet<T>) => SortedSet<T>} */
|
|
22
22
|
const intersect = cmp => a => b => toArray(intersectMerge(cmp)(a)(b))
|
|
23
23
|
|
|
24
|
+
const tailReduce = () => () => null
|
|
25
|
+
|
|
24
26
|
/** @type {<T>(cmp: Cmp<T>) => (a: sortedList.SortedList<T>) => (b: sortedList.SortedList<T>) => sortedList.SortedList<T>} */
|
|
25
|
-
const intersectMerge = cmp => genericMerge({ reduceOp: intersectReduce(cmp), tailReduce
|
|
27
|
+
const intersectMerge = cmp => genericMerge({ reduceOp: intersectReduce(cmp), tailReduce })(null)
|
|
26
28
|
|
|
27
29
|
/** @type {<T,S>(cmp: Cmp<T>) => sortedList.ReduceOp<T,S>} */
|
|
28
30
|
const intersectReduce = cmp => state => a => b => {
|
|
@@ -30,8 +32,6 @@ const intersectReduce = cmp => state => a => b => {
|
|
|
30
32
|
return [sign === 0 ? a : null, sign, state]
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
const intersectTail = () => () => null
|
|
34
|
-
|
|
35
35
|
/** @type {<T>(cmp: Cmp<T>) => (value: T) => (set: SortedSet<T>) => boolean} */
|
|
36
36
|
const has = cmp => value => set => find(cmp)(value)(set) === value
|
|
37
37
|
|