functionalscript 0.0.241 → 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.
@@ -1,5 +1,5 @@
1
1
  const json = require('../../../json')
2
- const seq = require('../../../types/sequence')
2
+ const seq = require('../../../types/list')
3
3
 
4
4
  /** @typedef {readonly[string, string]} DependencyJson */
5
5
 
@@ -1,7 +1,4 @@
1
1
  const _ = require('.')
2
- const json = require('../../../json')
3
- const { sort } = require('../../../types/object')
4
- const seq = require('../../../types/sequence')
5
2
 
6
3
  {
7
4
  if (!_.isDependenciesJson(undefined)) { throw 'error' }
@@ -1,9 +1,9 @@
1
- const seq = require("../../types/sequence")
1
+ const seq = require("../../types/list")
2
2
  const option = require("../../types/option")
3
3
  const { compose } = require("../../types/function")
4
4
  const dep = require("../package/dependencies")
5
5
  const { at } = require("../../types/object")
6
- const pack = require("../package")
6
+ // const pack = require("../package")
7
7
 
8
8
  /** @typedef {readonly string[]} Items */
9
9
 
@@ -18,7 +18,7 @@ const pack = require("../package")
18
18
  /** @type {(path: string) => readonly string[]} */
19
19
  const split = path => path.split('/')
20
20
 
21
- /** @type {(s: undefined|seq.Sequence<string>) => (items: string) => undefined|seq.Sequence<string>} */
21
+ /** @type {(s: undefined|seq.List<string>) => (items: string) => undefined|seq.List<string>} */
22
22
  const normItemsOp = prior => item => {
23
23
  if (prior === undefined) { return undefined }
24
24
  switch (item) {
@@ -29,17 +29,17 @@ const normItemsOp = prior => item => {
29
29
  return result.tail
30
30
  }
31
31
  default: {
32
- return seq.sequence(item)(prior)
32
+ return seq.nonEmpty(item)(prior)
33
33
  }
34
34
  }
35
35
  }
36
36
 
37
- /** @type {(items: seq.Sequence<string>) => seq.Sequence<string>|undefined} */
37
+ /** @type {(items: seq.List<string>) => seq.List<string>|undefined} */
38
38
  const normItems = compose(seq.reduce(normItemsOp)([]))(option.map(seq.reverse))
39
39
 
40
40
  /** @type {(local: string) => (path: string) => LocalPath|undefined} */
41
41
  const parseLocal = local => {
42
- /** @type {(path: string) => readonly[boolean, seq.Sequence<string>]} */
42
+ /** @type {(path: string) => readonly[boolean, seq.List<string>]} */
43
43
  const fSeq = path => {
44
44
  const pathSeq = split(path)
45
45
  switch (seq.first(undefined)(pathSeq)) {
@@ -61,9 +61,9 @@ const parseLocal = local => {
61
61
  return f
62
62
  }
63
63
 
64
- /** @typedef {readonly[string, seq.Sequence<string>]} IdPath */
64
+ /** @typedef {readonly[string, seq.List<string>]} IdPath */
65
65
 
66
- /** @type {(prior: readonly[string|undefined, seq.Sequence<string>]) => seq.Thunk<IdPath>} */
66
+ /** @type {(prior: readonly[string|undefined, seq.List<string>]) => seq.Thunk<IdPath>} */
67
67
  const variants = prior => () => {
68
68
  const [a, b] = prior
69
69
  const r = seq.next(b)
@@ -88,7 +88,7 @@ const mapDependency = d => ([external, internal]) => {
88
88
  * }} Path
89
89
  */
90
90
 
91
- /** @type {(d: dep.DependenciesJson) => (dir: boolean) => (items: seq.Sequence<string>) => Path|undefined} */
91
+ /** @type {(d: dep.DependenciesJson) => (dir: boolean) => (items: seq.List<string>) => Path|undefined} */
92
92
  const parseGlobal = d => dir => items => {
93
93
  if (d === undefined) { return undefined }
94
94
  const v = variants([undefined, items])
package/json/index.js CHANGED
@@ -1,7 +1,7 @@
1
- const seq = require('../types/sequence')
1
+ const seq = require('../types/list')
2
2
  const object = require('../types/object')
3
3
  const array = require('../types/array')
4
- const { todo } = require('../dev')
4
+ const op = require('../types/function/operator')
5
5
 
6
6
  /**
7
7
  * @typedef {{
@@ -13,9 +13,9 @@ const { todo } = require('../dev')
13
13
 
14
14
  /** @typedef {Object|boolean|string|number|null|Array} Unknown */
15
15
 
16
- /** @type {(value: Unknown) => (path: seq.Sequence<string>) => (src: Unknown|undefined) => Unknown} */
16
+ /** @type {(value: Unknown) => (path: seq.List<string>) => (src: Unknown|undefined) => Unknown} */
17
17
  const setProperty = value => {
18
- /** @type {(path: seq.Sequence<string>) => (src: Unknown|undefined) => Unknown} */
18
+ /** @type {(path: seq.List<string>) => (src: Unknown|undefined) => Unknown} */
19
19
  const f = path => src => {
20
20
  const result = seq.next(path)
21
21
  if (result === undefined) { return value }
@@ -26,10 +26,10 @@ const setProperty = value => {
26
26
  return f
27
27
  }
28
28
 
29
- /** @type {(_: string) => seq.Sequence<string>} */
29
+ /** @type {(_: string) => seq.List<string>} */
30
30
  const stringSerialize = input => [JSON.stringify(input)]
31
31
 
32
- /** @type {(_: number) => seq.Sequence<string>} */
32
+ /** @type {(_: number) => seq.List<string>} */
33
33
  const numberSerialize = input => [JSON.stringify(input)]
34
34
 
35
35
  const nullSerialize = ['null']
@@ -38,19 +38,19 @@ const trueSerialize = ['true']
38
38
 
39
39
  const falseSerialize = ['false']
40
40
 
41
- /** @type {(_: boolean) => seq.Sequence<string>} */
41
+ /** @type {(_: boolean) => seq.List<string>} */
42
42
  const boolSerialize = value => value ? trueSerialize : falseSerialize
43
43
 
44
44
  const colon = [':']
45
45
  const comma = [',']
46
46
 
47
- /** @type {seq.FoldOperator<seq.Sequence<string>>} */
47
+ /** @type {op.Fold<seq.List<string>>} */
48
48
  const joinOp = a => b => seq.flat([a, comma, b])
49
49
 
50
- /** @type {(input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
50
+ /** @type {(input: seq.List<seq.List<string>>) => seq.List<string>} */
51
51
  const join = seq.fold(joinOp)([])
52
52
 
53
- /** @type {(open: string) => (close: string) => (input: seq.Sequence<seq.Sequence<string>>) => seq.Sequence<string>} */
53
+ /** @type {(open: string) => (close: string) => (input: seq.List<seq.List<string>>) => seq.List<string>} */
54
54
  const list = open => close => {
55
55
  const seqOpen = [open]
56
56
  const seqClose = [close]
@@ -63,19 +63,19 @@ const arrayList = list('[')(']')
63
63
 
64
64
  /** @typedef {object.Entry<Unknown>} Entry*/
65
65
 
66
- /** @typedef {(seq.Sequence<Entry>)} Entries */
66
+ /** @typedef {(seq.List<Entry>)} Entries */
67
67
 
68
68
  /** @typedef {(entries: Entries) => Entries} MapEntries */
69
69
 
70
- /** @type {(mapEntries: MapEntries) => (value: Unknown) => seq.Sequence<string>} */
70
+ /** @type {(mapEntries: MapEntries) => (value: Unknown) => seq.List<string>} */
71
71
  const serialize = sort => {
72
- /** @type {(kv: readonly[string, Unknown]) => seq.Sequence<string>} */
72
+ /** @type {(kv: readonly[string, Unknown]) => seq.List<string>} */
73
73
  const propertySerialize = ([k, v]) => seq.flat([
74
74
  stringSerialize(k),
75
75
  colon,
76
76
  f(v)
77
77
  ])
78
- /** @type {(object: Object) => seq.Sequence<string>} */
78
+ /** @type {(object: Object) => seq.List<string>} */
79
79
  const objectSerialize = input => {
80
80
  const entries = Object.entries(input)
81
81
  const sortedEntries = sort(entries)
@@ -83,12 +83,12 @@ const serialize = sort => {
83
83
  const serializedEntries = seq.map(propertySerialize)(sortedEntries)
84
84
  return objectList(serializedEntries)
85
85
  }
86
- /** @type {(input: Array) => seq.Sequence<string>} */
86
+ /** @type {(input: Array) => seq.List<string>} */
87
87
  const arraySerialize = input => {
88
88
  const serializedEntries = seq.map(f)(input)
89
89
  return arrayList(serializedEntries)
90
90
  }
91
- /** @type {(value: Unknown) => seq.Sequence < string >} */
91
+ /** @type {(value: Unknown) => seq.List < string >} */
92
92
  const f = value => {
93
93
  switch (typeof value) {
94
94
  case 'boolean': { return boolSerialize(value) }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "functionalscript",
3
- "version": "0.0.241",
3
+ "version": "0.0.242",
4
4
  "description": "FunctionalScript is a functional subset of JavaScript",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const i = require('./')
2
2
 
3
- require('./types/sequence/test')
3
+ require('./types/list/test')
4
4
  require('./types/btree/test')
5
5
  require('./json/test')
6
6
  require('./types/object/test')
@@ -1,5 +1,5 @@
1
1
  const option = require('../option')
2
- const seq = require('../sequence')
2
+ const seq = require('../list')
3
3
 
4
4
  /**
5
5
  * @template T
@@ -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
@@ -303,7 +303,7 @@ const replaceVisitor = {
303
303
  notFound: notFoundGet,
304
304
  }
305
305
 
306
- /** @type {<T>(node: Node<T>) => seq.Sequence<T>} */
306
+ /** @type {<T>(node: Node<T>) => seq.List<T>} */
307
307
  const values = node => () => {
308
308
  const f = () => {
309
309
  switch (node.length) {
@@ -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
+ }
@@ -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
 
@@ -3,7 +3,7 @@ const btree = require('../btree')
3
3
  const { getVisitor, setVisitor, values } = require("../btree")
4
4
  const compare = require("../function/compare")
5
5
  const { cmp } = require("../function/compare")
6
- const seq = require("../sequence")
6
+ const seq = require("../list")
7
7
 
8
8
  /** @typedef {compare.Sign} Sign */
9
9
 
@@ -54,15 +54,15 @@ const set = name => value => map => {
54
54
  }
55
55
  }
56
56
 
57
- /** @type {<T>(map: Map<T>) => seq.Sequence<Entry<T>>} */
57
+ /** @type {<T>(map: Map<T>) => seq.List<Entry<T>>} */
58
58
  const entries = map => map === undefined ? [] : values(map)
59
59
 
60
60
  /** @type {<T>(map: Map<T>) => (entry: Entry<T>) => Map<T>} */
61
61
  const setOp = map => ([name, value]) => set(name)(value)(map)
62
62
 
63
- /** @type {<T>(entries: seq.Sequence<Entry<T>>) => Map<T>} */
63
+ /** @type {<T>(entries: seq.List<Entry<T>>) => Map<T>} */
64
64
  const fromEntries = entries => {
65
- /** @typedef {typeof entries extends seq.Sequence<Entry<infer T>> ? T : never} T */
65
+ /** @typedef {typeof entries extends seq.List<Entry<infer T>> ? T : never} T */
66
66
  return seq.reduce(setOp)(/** @type {Map<T>} */(undefined))(entries)
67
67
  }
68
68
 
package/types/map/test.js CHANGED
@@ -1,5 +1,5 @@
1
1
  const { at, set, empty, entries } = require('.')
2
- const seq = require('../sequence')
2
+ const seq = require('../list')
3
3
 
4
4
  {
5
5
  let m = set('a')(1)(undefined)
@@ -1,6 +1,5 @@
1
- const seq = require('../sequence')
1
+ const seq = require('../list')
2
2
  const map = require('../map')
3
- const { compose } = require('../function')
4
3
 
5
4
  /**
6
5
  * @template T
@@ -17,7 +16,7 @@ const { compose } = require('../function')
17
16
  /** @type {(name: string) => <T>(object: Map<T>) => T|undefined} */
18
17
  const at = name => object => Object.getOwnPropertyDescriptor(object, name)?.value
19
18
 
20
- /** @type {<T>(entries: seq.Sequence<Entry<T>>) => seq.Sequence<Entry<T>>} */
19
+ /** @type {<T>(entries: seq.List<Entry<T>>) => seq.List<Entry<T>>} */
21
20
  const sort = entries => map.entries(map.fromEntries(entries))
22
21
 
23
22
  module.exports = {
@@ -1,68 +0,0 @@
1
- # Sequences
2
-
3
- Sequence types:
4
-
5
- - Sequence
6
- - Array
7
- - Iterable
8
- - AsyncIterable
9
-
10
- # Sequence Types
11
-
12
- ```ts
13
- type Sequence<T> =
14
- readonly T[] |
15
- Thunk<T> |
16
-
17
- type Thunk<T> = () => Node<T>
18
-
19
- type Node<T> =
20
- undefined |
21
- { readonly first: T, readonly tail: Sequence<T> } |
22
- readonly[Sequence<T>, Sequence<T>]
23
- ```
24
-
25
- ## Functions
26
-
27
- See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array
28
-
29
- - `length: Sequence<infer T> => number`
30
- - `at: number => Sequence<infer T> = T|undefined`
31
- - `concat: Sequence<infer T> => Sequence<T> => Sequence<T>`
32
- - `entries: Sequence<infer T> => Sequence<[number, T]>`
33
- - `every: (infer T => boolean) => Sequence<T> => boolean`
34
- - `filter: (infer T => boolean) => Sequence<T> => Sequence<T>`
35
- - `find: (infer T => boolean) => Sequence<T> => T`
36
- - `findIndex: (infer T => boolean) => Sequence<T> => number`
37
- - `flat: Sequence<Sequence<T>> => Sequence<T>`
38
- - `flatMap: (infer T => Sequence<infer R>) => Sequence<T> => Sequence<R>`
39
- - `includes: infer T => Sequence<T> => boolean`
40
- - `indexOf: infer T => Sequence<T> => number`
41
- - `join: string => Sequence<string> => string`
42
- - `lastIndexOf: infer T => Sequence<T> => number`
43
- - `map: (infer T => infer R) => Sequence<T> => Sequence<R>`
44
- - `reduce: ...Scan<T, R> => Sequence<T> => R`
45
- - `some: (infer T => boolean) => Sequence<T> => boolean`
46
-
47
- ### Priority 2.
48
-
49
- - `slice: number => number => Sequence<T> => Sequence<T>`
50
- - `reduceRight: ...Scan<T, R> => Sequence<T> => R`
51
- - `toLocalString: Locales => Sequence<T> => string`
52
-
53
- ### Priority 3.
54
-
55
- - `keys: Sequence<T> => Sequence<string>`
56
- - `values: Sequence<infer T> => Sequence<T>`
57
-
58
- ## Prohibited Array Operations
59
-
60
- - `copyWithin`
61
- - `fill`
62
- - `pop`
63
- - `push`
64
- - `reverse`
65
- - `shift`
66
- - `sort`
67
- - `splice`
68
- - `unshift`
@@ -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
- }