t-tasks 1.0.1 → 1.0.2

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/src/either.ts CHANGED
@@ -41,7 +41,7 @@ export interface Right<R, L> {
41
41
  * @param op.left function to be invoked with underlying error in case of 'left'
42
42
  * @returns self
43
43
  */
44
- matchTap(op: { right: (value: R) => void; left: (error: any) => void }): this;
44
+ matchTap(op: { right: (value: R) => void; left: (error: L) => void }): this;
45
45
 
46
46
  /**
47
47
  * Either transformer function
@@ -85,9 +85,9 @@ export interface Right<R, L> {
85
85
  * @returns 'right op.right(value)' or 'right op.left(error)'
86
86
  */
87
87
  // Right case
88
- matchMap<R2, R3 = R2>(this: Right<R, L>, op: { right: (value: R) => R2; left: (error: any) => R3 }): Right<R2, never>;
88
+ matchMap<R2, R3 = R2>(this: Right<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): Right<R2, never>;
89
89
  // General case
90
- matchMap<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: any) => R3 }): Right<R2 | R3, never>;
90
+ matchMap<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): Right<R2 | R3, never>;
91
91
 
92
92
  /**
93
93
  * Either composition function
@@ -144,25 +144,25 @@ export interface Right<R, L> {
144
144
  * @returns 'op(value)' or 'op(error)'
145
145
  */
146
146
  // Right cases
147
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Right<R3, L3> }): Right<R2, never>;
148
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Right<R3, L3> }): Left<never, L2>;
149
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Left<R3, L3> }): Right<R2, never>;
150
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Left<R3, L3> }): Left<never, L2>;
151
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Right<R3, L3> }): Either<R2, L2>;
152
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Left<R3, L3> }): Either<R2, L2>;
153
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Either<R3, L3> }): Right<R2, never>;
154
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Either<R3, L3> }): Left<never, L2>;
155
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R2, L2>;
147
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R2, never>;
148
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Right<R3, L3> }): Left<never, L2>;
149
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Left<R3, L3> }): Right<R2, never>;
150
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Left<R3, L3> }): Left<never, L2>;
151
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Right<R3, L3> }): Either<R2, L2>;
152
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Left<R3, L3> }): Either<R2, L2>;
153
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Either<R3, L3> }): Right<R2, never>;
154
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Either<R3, L3> }): Left<never, L2>;
155
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Right<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R2, L2>;
156
156
  // General cases
157
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Right<R3, L3> }): Right<R2 | R3, never>;
158
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Right<R3, L3> }): Either<R3, L2>;
159
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Left<R3, L3> }): Either<R2, L3>;
160
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Left<R3, L3> }): Left<never, L2 | L3>;
161
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Right<R3, L3> }): Either<R2 | R3, L2>;
162
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Left<R3, L3> }): Either<R2, L2 | L3>;
163
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R2 | R3, L3>;
164
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R3, L2 | L3>;
165
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R2 | R3, L2 | L3>;
157
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R2 | R3, never>;
158
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Right<R3, L3> }): Either<R3, L2>;
159
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Left<R3, L3> }): Either<R2, L3>;
160
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Left<R3, L3> }): Left<never, L2 | L3>;
161
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Right<R3, L3> }): Either<R2 | R3, L2>;
162
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Left<R3, L3> }): Either<R2, L2 | L3>;
163
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R2 | R3, L3>;
164
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R3, L2 | L3>;
165
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R2 | R3, L2 | L3>;
166
166
 
167
167
  /**
168
168
  * Either type guard for 'right'
@@ -191,6 +191,15 @@ export interface Right<R, L> {
191
191
  * ```
192
192
  */
193
193
  isLeft(): this is Left<R, L>;
194
+
195
+ /**
196
+ * Wrap Maybe to singleton generator
197
+ *
198
+ * Userful in order to avoid ambiguous yied types
199
+ *
200
+ * @returns generator of Maybe wrapping this
201
+ */
202
+ generator: EitherGeneratorFunction<[], R, Right<R, L>, R>
194
203
  }
195
204
 
196
205
  /**
@@ -236,7 +245,7 @@ export interface Left<R, L> {
236
245
  * @param op.left function to be invoked with underlying error in case of 'left'
237
246
  * @returns self
238
247
  */
239
- matchTap(op: { right: (value: R) => void; left: (error: any) => void }): this;
248
+ matchTap(op: { right: (value: R) => void; left: (error: L) => void }): this;
240
249
 
241
250
  /**
242
251
  * Either transformer function
@@ -280,9 +289,9 @@ export interface Left<R, L> {
280
289
  * @returns 'right op.right(value)' or 'right op.left(error)'
281
290
  */
282
291
  // Left case
283
- matchMap<R2, R3 = R2>(this: Left<R, L>, op: { right: (value: R) => R2; left: (error: any) => R3 }): Right<R3, never>;
292
+ matchMap<R2, R3 = R2>(this: Left<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): Right<R3, never>;
284
293
  // General case
285
- matchMap<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: any) => R3 }): Right<R2 | R3, never>;
294
+ matchMap<R2, R3 = R2>(this: Either<R, L>, op: { right: (value: R) => R2; left: (error: L) => R3 }): Right<R2 | R3, never>;
286
295
 
287
296
  /**
288
297
  * Either composition function
@@ -339,25 +348,25 @@ export interface Left<R, L> {
339
348
  * @returns 'op(value)' or 'op(error)'
340
349
  */
341
350
  // Left cases
342
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Right<R3, L3> }): Right<R3, never>;
343
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Right<R3, L3> }): Right<R3, never>;
344
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Left<R3, L3> }): Left<never, L3>;
345
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Left<R3, L3> }): Left<never, L3>;
346
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Right<R3, L3> }): Right<R3, never>;
347
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Left<R3, L3> }): Left<never, L3>;
348
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R3, L3>;
349
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R3, L3>;
350
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R3, L3>;
351
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R3, never>;
352
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R3, never>;
353
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Left<R3, L3> }): Left<never, L3>;
354
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Left<R3, L3> }): Left<never, L3>;
355
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R3, never>;
356
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Left<R3, L3> }): Left<never, L3>;
357
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R3, L3>;
358
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R3, L3>;
359
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Left<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R3, L3>;
351
360
  // General cases
352
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Right<R3, L3> }): Right<R2 | R3, never>;
353
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Right<R3, L3> }): Either<R3, L2>;
354
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Left<R3, L3> }): Either<R2, L3>;
355
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Left<R3, L3> }): Left<never, L2 | L3>;
356
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Right<R3, L3> }): Either<R2 | R3, L2>;
357
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Left<R3, L3> }): Either<R2, L2 | L3>;
358
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R2 | R3, L3>;
359
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R3, L2 | L3>;
360
- matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: any) => Either<R3, L3> }): Either<R2 | R3, L2 | L3>;
361
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Right<R3, L3> }): Right<R2 | R3, never>;
362
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Right<R3, L3> }): Either<R3, L2>;
363
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Left<R3, L3> }): Either<R2, L3>;
364
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Left<R3, L3> }): Left<never, L2 | L3>;
365
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Right<R3, L3> }): Either<R2 | R3, L2>;
366
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Left<R3, L3> }): Either<R2, L2 | L3>;
367
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Right<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R2 | R3, L3>;
368
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Left<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R3, L2 | L3>;
369
+ matchChain<R2, L2, R3 = R2, L3 = L2>(this: Either<R, L>, op: { right: (value: R) => Either<R2, L2>; left: (error: L) => Either<R3, L3> }): Either<R2 | R3, L2 | L3>;
361
370
 
362
371
  /**
363
372
  * Either type guard for 'right'
@@ -386,6 +395,15 @@ export interface Left<R, L> {
386
395
  * ```
387
396
  */
388
397
  isLeft(): this is Left<R, L>;
398
+
399
+ /**
400
+ * Wrap Maybe to singleton generator
401
+ *
402
+ * Userful in order to avoid ambiguous yied types
403
+ *
404
+ * @returns generator of Maybe wrapping this
405
+ */
406
+ generator: EitherGeneratorFunction<[], R, Left<R, L>, R>
389
407
  }
390
408
 
391
409
  /**
@@ -431,6 +449,9 @@ export namespace Left {
431
449
  }
432
450
  }
433
451
 
452
+ export type EitherGenerator<T, TT extends Either<T, any>, R> = Generator<TT, R, T>;
453
+ export type EitherGeneratorFunction<A extends unknown[], T, TT extends Either<T, any>, R> = (...args: A) => EitherGenerator<T, TT, R>;
454
+
434
455
  export namespace Either {
435
456
  /**
436
457
  * Right monad constructor
@@ -529,7 +550,7 @@ export namespace Either {
529
550
  * @param eithers a list of Either
530
551
  * @returns true in case at least one list element is Right
531
552
  */
532
- export function someRight<R, L>(eithers: Either<R, L>[]): eithers is Right<R, never>[] {
553
+ export function someRight<R, L>(eithers: Either<R, L>[]): boolean {
533
554
  return eithers.some(Either.isRight);
534
555
  }
535
556
 
@@ -549,9 +570,38 @@ export namespace Either {
549
570
  * @param eithers a list of Either
550
571
  * @returns true in case at least one list element is Left
551
572
  */
552
- export function someLeft<R, L>(eithers: Either<R, L>[]): eithers is Left<never, L>[] {
573
+ export function someLeft<R, L>(eithers: Either<R, L>[]): boolean {
553
574
  return eithers.some(Either.isLeft);
554
575
  }
576
+
577
+ /**
578
+ * Create compound Either from generator function
579
+ *
580
+ * Applying yield to a Maybe within the generator function unwraps the Maybe and returns underlying value in case of success
581
+ * However the convinient option for typescript is to use ```yield* maybe.generator()``` as othervise one may have to deal with union types
582
+ *
583
+ * @template TT yielded Maybe type
584
+ * @template R returned underlying type
585
+ * @param maybeGeneratorFunction Maybe generator function
586
+ * @returns Just wrapping the result of generator function or Nothing
587
+ * ```
588
+ */
589
+ export function generate<T, TT extends Either<T, any>, R>(eitherGeneratorFunction: EitherGeneratorFunction<[], T, TT, R>): Either<R, any> {
590
+ const generator = eitherGeneratorFunction();
591
+
592
+ const sequentor = (next: IteratorResult<TT, R>): Either<R, any> => {
593
+ return next.done ? (
594
+ Either.right(next.value)
595
+ ) : (
596
+ next.value.matchChain<R, any>({
597
+ right: (value) => sequentor(generator.next(value)),
598
+ left: Either.left,
599
+ })
600
+ );
601
+ };
602
+
603
+ return Either.right(undefined).chain(() => sequentor(generator.next()));
604
+ }
555
605
  }
556
606
 
557
607
  /// --------------------------------------------------------------------------------------
@@ -596,6 +646,11 @@ class RightClass<R> implements Right<R, never> {
596
646
  matchChain<TT extends Either<unknown, unknown>>(op: { right: (value: R) => TT }) {
597
647
  return this.chain(op.right);
598
648
  }
649
+ generator() {
650
+ return (function*(value) {
651
+ return (yield value) as R;
652
+ })(this);
653
+ }
599
654
  }
600
655
 
601
656
  class LeftClass<L> implements Left<never, L> {
@@ -627,13 +682,18 @@ class LeftClass<L> implements Left<never, L> {
627
682
  isLeft(): this is Left<never, L> {
628
683
  return true;
629
684
  }
630
- matchTap(op: { left: (error: any) => void }) {
685
+ matchTap(op: { left: (error: L) => void }) {
631
686
  return this.orTap(op.left);
632
687
  }
633
- matchMap<R2>(op: { left: (error: any) => R2 }) {
688
+ matchMap<R2>(op: { left: (error: L) => R2 }) {
634
689
  return this.orMap(op.left);
635
690
  }
636
- matchChain<TT extends Either<unknown, unknown>>(op: { left: (error: any) => TT }) {
691
+ matchChain<TT extends Either<unknown, unknown>>(op: { left: (error: L) => TT }) {
637
692
  return this.orChain(op.left);
638
693
  }
694
+ generator() {
695
+ return (function*(value) {
696
+ return (yield value) as never;
697
+ })(this);
698
+ }
639
699
  }
package/src/maybe.ts CHANGED
@@ -186,6 +186,15 @@ export interface Just<R> {
186
186
  * ```
187
187
  */
188
188
  isNothing(): this is Nothing<R>;
189
+
190
+ /**
191
+ * Wrap Maybe to singleton generator
192
+ *
193
+ * Userful in order to avoid ambiguous yied types
194
+ *
195
+ * @returns generator of Maybe wrapping this
196
+ */
197
+ generator: MaybeGeneratorFunction<[], R, Just<R>, R>
189
198
  }
190
199
 
191
200
  /**
@@ -372,6 +381,15 @@ export interface Nothing<R> {
372
381
  * ```
373
382
  */
374
383
  isNothing(): this is Nothing<R>;
384
+
385
+ /**
386
+ * Wrap Maybe to singleton generator
387
+ *
388
+ * Userful in order to avoid ambiguous yied types
389
+ *
390
+ * @returns generator of Maybe wrapping this
391
+ */
392
+ generator: MaybeGeneratorFunction<[], R, Nothing<R>, R>
375
393
  }
376
394
 
377
395
  /**
@@ -401,6 +419,9 @@ export namespace Just {
401
419
 
402
420
  export namespace Nothing {}
403
421
 
422
+ export type MaybeGenerator<T, TT extends Maybe<T>, R> = Generator<TT, R, T>;
423
+ export type MaybeGeneratorFunction<A extends unknown[], T, TT extends Maybe<T>, R> = (...args: A) => MaybeGenerator<T, TT, R>;
424
+
404
425
  export namespace Maybe {
405
426
  /**
406
427
  * Non-empty monad constructor
@@ -495,7 +516,7 @@ export namespace Maybe {
495
516
  * @param maybes a list of Maybe
496
517
  * @returns true in case al east one list element is Just
497
518
  */
498
- export function someJust<R>(maybes: Maybe<R>[]): maybes is Just<R>[] {
519
+ export function someJust<R>(maybes: Maybe<R>[]): boolean {
499
520
  return maybes.some(Maybe.isJust);
500
521
  }
501
522
 
@@ -515,9 +536,38 @@ export namespace Maybe {
515
536
  * @param maybes a list of Maybe
516
537
  * @returns true in case at least one list element is Nothing
517
538
  */
518
- export function someNothing<R>(maybes: Maybe<R>[]): maybes is Nothing<never>[] {
539
+ export function someNothing<R>(maybes: Maybe<R>[]): boolean {
519
540
  return maybes.some(Maybe.isNothing);
520
541
  }
542
+
543
+ /**
544
+ * Create compound Maybe from generator function
545
+ *
546
+ * Applying yield to a Maybe within the generator function unwraps the Maybe and returns underlying value in case of success
547
+ * However the convinient option for typescript is to use ```yield* maybe.generator()``` as othervise one may have to deal with union types
548
+ *
549
+ * @template TT yielded Maybe type
550
+ * @template R returned underlying type
551
+ * @param maybeGeneratorFunction Maybe generator function
552
+ * @returns Just wrapping the result of generator function or Nothing
553
+ * ```
554
+ */
555
+ export function generate<T, TT extends Maybe<T>, R>(maybeGeneratorFunction: MaybeGeneratorFunction<[], T, TT, R>): Maybe<R> {
556
+ const generator = maybeGeneratorFunction();
557
+
558
+ const sequentor = (next: IteratorResult<TT, R>): Maybe<R> => {
559
+ return next.done ? (
560
+ Maybe.just(next.value)
561
+ ) : (
562
+ next.value.matchChain<R>({
563
+ just: (value) => sequentor(generator.next(value)),
564
+ nothing: Maybe.nothing,
565
+ })
566
+ );
567
+ };
568
+
569
+ return Maybe.just(undefined).chain(() => sequentor(generator.next()));
570
+ }
521
571
  }
522
572
 
523
573
  /// --------------------------------------------------------------------------------------
@@ -562,6 +612,11 @@ class JustClass<R> implements Just<R> {
562
612
  matchChain<RR extends Maybe<unknown>>(op: { just: (value: R) => RR }) {
563
613
  return this.chain(op.just);
564
614
  }
615
+ generator() {
616
+ return (function*(value) {
617
+ return (yield value) as R;
618
+ })(this);
619
+ }
565
620
  }
566
621
 
567
622
  class NothingClass implements Nothing<never> {
@@ -600,6 +655,11 @@ class NothingClass implements Nothing<never> {
600
655
  matchChain<RR extends Maybe<unknown>>(op: { nothing: () => RR }) {
601
656
  return this.orChain(op.nothing);
602
657
  }
658
+ generator() {
659
+ return (function*(value) {
660
+ return (yield value) as never;
661
+ })(this);
662
+ }
603
663
  }
604
664
 
605
665
  const staticNothing = new NothingClass();
package/src/task.ts CHANGED
@@ -364,6 +364,17 @@ export namespace Task {
364
364
  return Task.fromPromise(promise).generator();
365
365
  }
366
366
 
367
+ /**
368
+ * Convinience shortcut for yielding timers
369
+ *
370
+ * @template R returned generator resolve type
371
+ * @param promise promise to be resolved
372
+ * @returns generator to be be used with yield*
373
+ */
374
+ export function timeoutGenerator(delay: number) {
375
+ return Task.timeout(delay).generator();
376
+ }
377
+
367
378
  /**
368
379
  * Lift from function returning value/promise to function returning task resolving to that value
369
380
  *
@@ -423,13 +434,15 @@ export namespace Task {
423
434
  const generator = taskGeneratorFunction();
424
435
 
425
436
  const sequentor = (next: IteratorResult<TT, R>): Task<R> => {
426
- return next.done
427
- ? Task.resolved(next.value)
428
- : next.value.matchChain<R>({
429
- resolved: (value) => sequentor(generator.next(value)),
430
- rejected: (error) => sequentor(generator.throw(error)),
431
- canceled: Task.canceled,
432
- });
437
+ return next.done ? (
438
+ Task.resolved(next.value)
439
+ ) : (
440
+ next.value.matchChain<R>({
441
+ resolved: (value) => sequentor(generator.next(value)),
442
+ rejected: (error) => sequentor(generator.throw(error)),
443
+ canceled: Task.canceled,
444
+ })
445
+ );
433
446
  };
434
447
 
435
448
  return Task.resolved(undefined).chain(() => sequentor(generator.next()));