UNPKG

51.9 kBJavaScriptView Raw
1/*!
2 * Copyright (c) 2017-2018 by The Funfix Project Developers.
3 * Some rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17import * as std from "./std";
18import { NoSuchElementError } from "./errors";
19import { fantasyLandRegister } from "./internals";
20/**
21 * Represents a value of one of two possible types (a disjoint union).
22 *
23 * A common use of Either is as an alternative to [[Option]] for dealing
24 * with possible missing values. In this usage [[Option.none]] is replaced
25 * with [[Either.left]] which can contain useful information and
26 * [[Option.some]] is replaced with [[Either.right]].
27 *
28 * Convention dictates that `left` is used for failure and `right` is used
29 * for success. Note that this `Either` type is right-biased, meaning that
30 * operations such as `map`, `flatMap` and `filter` work on the `right` value
31 * and if you want to work on the `left` value, then you need to do a `swap`.
32 *
33 * For example, you could use `Either<String, Int>` to detect whether an
34 * input is a string or an number:
35 *
36 * ```typescript
37 * function tryParseInt(str: string): Either<string, number> {
38 * const i = parseInt(value)
39 * return isNaN(i) ? Left(str) : Right(i)
40 * }
41 *
42 * const result = tryParseInt("not an int")
43 * if (result.isRight()) {
44 * console.log(`Increment: ${result.get}`)
45 * } else {
46 * console.log(`ERROR: could not parse ${result.swap.get}`)
47 * }
48 * ```
49 *
50 * @final
51 */
52export class Either {
53 constructor(value, tag) {
54 this._isRight = tag === "right";
55 this.value = value;
56 }
57 /**
58 * Returns `true` if this is a `left`, `false` otherwise.
59 *
60 * ```typescript
61 * Left("hello").isLeft() // true
62 * Right(10).isLeft() // false
63 * ```
64 */
65 isLeft() { return !this._isRight; }
66 /**
67 * Returns `true` if this is a `right`, `false` otherwise.
68 *
69 * ```typescript
70 * Left("hello").isRight() // false
71 * Right(10).isRight() // true
72 * ```
73 */
74 isRight() { return this._isRight; }
75 /**
76 * Returns true if this is a Right and its value is equal to `elem`
77 * (as determined by the `equals` protocol), returns `false` otherwise.
78 *
79 * ```typescript
80 * // True
81 * Right("something").contains("something")
82 *
83 * // False because the values are different
84 * Right("something").contains("anything") // false
85 *
86 * // False because the source is a `left`
87 * Left("something").contains("something") // false
88 * ```
89 */
90 contains(elem) {
91 return this._isRight && std.is(this.value, elem);
92 }
93 /**
94 * Returns `false` if the source is a `left`, or returns the result
95 * of the application of the given predicate to the `right` value.
96 *
97 * ```typescript
98 * // True, because it is a right and predicate holds
99 * Right(20).exists(n => n > 10)
100 *
101 * // False, because the predicate returns false
102 * Right(10).exists(n => n % 2 != 0)
103 *
104 * // False, because it is a left
105 * Left(10).exists(n => n == 10)
106 * ```
107 */
108 exists(p) {
109 return this._isRight && p(this.value);
110 }
111 /**
112 * Filters `right` values with the given predicate, returning
113 * the value generated by `zero` in case the source is a `right`
114 * value and the predicate doesn't hold.
115 *
116 * Possible outcomes:
117 *
118 * - Returns the existing value of `right` if this is a `right` value and the
119 * given predicate `p` holds for it
120 * - Returns `Left(zero())` if this is a `right` value
121 * and the given predicate `p` does not hold
122 * - Returns the current "left" value, if the source is a `Left`
123 *
124 * ```typescript
125 * Right(12).filterOrElse(x => x > 10, () => -1) // Right(12)
126 * Right(7).filterOrElse(x => x > 10, () => -1) // Left(-1)
127 * Left(7).filterOrElse(x => false, () => -1) // Left(7)
128 * ```
129 */
130 filterOrElse(p, zero) {
131 return this._isRight
132 ? (p(this.value) ? this : Left(zero()))
133 : this;
134 }
135 /**
136 * Binds the given function across `right` values.
137 *
138 * This operation is the monadic "bind" operation.
139 * It can be used to *chain* multiple `Either` references.
140 */
141 flatMap(f) {
142 return this._isRight ? f(this.value) : this;
143 }
144 /** Alias for [[flatMap]]. */
145 chain(f) {
146 return this.flatMap(f);
147 }
148 /**
149 * `Applicative` apply operator.
150 *
151 * Resembles {@link map}, but the passed mapping function is
152 * lifted in the `Either` context.
153 */
154 ap(ff) {
155 return ff.flatMap(f => this.map(f));
156 }
157 /**
158 * Applies the `left` function to [[Left]] values, and the
159 * `right` function to [[Right]] values and returns the result.
160 *
161 * ```typescript
162 * const maybeNum: Either<string, number> =
163 * tryParseInt("not a number")
164 *
165 * const result: string =
166 * maybeNum.fold(
167 * str => `Could not parse string: ${str}`,
168 * num => `Success: ${num}`
169 * )
170 * ```
171 */
172 fold(left, right) {
173 return this._isRight ? right(this.value) : left(this.value);
174 }
175 /**
176 * Returns true if the source is a `left` or returns
177 * the result of the application of the given predicate to the
178 * `right` value.
179 *
180 * ```typescript
181 * // True, because it is a `left`
182 * Left("hello").forAll(x => x > 10)
183 *
184 * // True, because the predicate holds
185 * Right(20).forAll(x => x > 10)
186 *
187 * // False, it's a right and the predicate doesn't hold
188 * Right(7).forAll(x => x > 10)
189 * ```
190 */
191 forAll(p) {
192 return !this._isRight || p(this.value);
193 }
194 /**
195 * Returns the `Right` value, if the source has one,
196 * otherwise throws an exception.
197 *
198 * WARNING!
199 *
200 * This function is partial, the `Either` must be a `Right`, otherwise
201 * a runtime exception will get thrown. Use with care.
202 *
203 * @throws [[NoSuchElementError]] in case the the `Either` is a `Left`
204 */
205 get() {
206 if (this._isRight)
207 return this.value;
208 throw new NoSuchElementError("left.get()");
209 }
210 /**
211 * Returns the value from this `right` or the given `fallback`
212 * value if this is a `left`.
213 *
214 * ```typescript
215 * Right(10).getOrElse(27) // 10
216 * Left(10).getOrElse(27) // 27
217 * ```
218 */
219 getOrElse(fallback) {
220 return this._isRight ? this.value : fallback;
221 }
222 /**
223 * Returns the value from this `right` or a value generated
224 * by the given `thunk` if this is a `left`.
225 *
226 * ```typescript
227 * Right(10).getOrElseL(() => 27) // 10
228 * Left(10).getOrElseL(() => 27) // 27
229 * ```
230 */
231 getOrElseL(thunk) {
232 return this._isRight ? this.value : thunk();
233 }
234 /**
235 * Transform the source if it is a `right` with the given
236 * mapping function.
237 *
238 * ```typescript
239 * Right(10).map(x => x + 17) // right(27)
240 * Left(10).map(x => x + 17) // left(10)
241 * ```
242 */
243 map(f) {
244 return this._isRight
245 ? Right(f(this.value))
246 : this;
247 }
248 /**
249 * Executes the given side-effecting function if the
250 * source is a `right` value.
251 *
252 * ```typescript
253 * Right(12).forAll(console.log) // prints 12
254 * Left(10).forAll(console.log) // silent
255 * ```
256 */
257 forEach(cb) {
258 if (this._isRight)
259 cb(this.value);
260 }
261 /**
262 * If this is a `left`, then return the left value as a `right`
263 * or vice versa.
264 *
265 * ```typescript
266 * Right(10).swap() // left(10)
267 * Left(20).swap() // right(20)
268 * ```
269 */
270 swap() {
271 return this._isRight
272 ? Left(this.value)
273 : Right(this.value);
274 }
275 /**
276 * Returns an `Option.some(right)` if the source is a `right` value,
277 * or `Option.none` in case the source is a `left` value.
278 */
279 toOption() {
280 return this._isRight ? Some(this.value) : None;
281 }
282 /**
283 * Implements {@link IEquals.equals}.
284 *
285 * @param that is the right hand side of the equality check
286 */
287 equals(that) {
288 // tslint:disable-next-line:strict-type-predicates
289 if (that == null)
290 return false;
291 return this._isRight === that._isRight && std.is(this.value, that.value);
292 }
293 /** Implements {@link IEquals.hashCode}. */
294 hashCode() {
295 return this._isRight
296 ? std.hashCode(this.value) << 2
297 : std.hashCode(this.value) << 3;
298 }
299 /**
300 * Builds a pure `Either` value.
301 *
302 * This operation is the pure `Applicative` operation for lifting
303 * a value in the `Either` context.
304 */
305 static pure(value) {
306 return new TRight(value);
307 }
308 /**
309 * Builds a left value, equivalent with {@link Left}.
310 */
311 static left(value) {
312 return Left(value);
313 }
314 /**
315 * Builds a right value, equivalent with {@link Right}.
316 */
317 static right(value) {
318 return Right(value);
319 }
320 /**
321 * Maps 2 `Either` values by the mapping function, returning a new
322 * `Either` reference that is a `Right` only if both `Either` values are
323 * `Right` values, otherwise it returns the first `Left` value noticed.
324 *
325 * ```typescript
326 * // Yields Right(3)
327 * Try.map2(Right(1), Right(2),
328 * (a, b) => a + b
329 * )
330 *
331 * // Yields Left, because the second arg is a Left
332 * Try.map2(Right(1), Left("error"),
333 * (a, b) => a + b
334 * )
335 * ```
336 *
337 * This operation is the `Applicative.map2`.
338 */
339 static map2(fa1, fa2, f) {
340 if (fa1.isLeft())
341 return fa1;
342 if (fa2.isLeft())
343 return fa2;
344 return Right(f(fa1.value, fa2.value));
345 }
346 /**
347 * Maps 3 `Either` values by the mapping function, returning a new
348 * `Either` reference that is a `Right` only if all 3 `Either` values are
349 * `Right` values, otherwise it returns the first `Left` value noticed.
350 *
351 * ```typescript
352 * // Yields Right(6)
353 * Try.map3(Right(1), Right(2), Right(3),
354 * (a, b, c) => a + b + c
355 * )
356 *
357 * // Yields Left, because the second arg is a Left
358 * Try.map3(Right(1), Left("error"), Right(3),
359 * (a, b, c) => a + b + c
360 * )
361 * ```
362 */
363 static map3(fa1, fa2, fa3, f) {
364 if (fa1.isLeft())
365 return fa1;
366 if (fa2.isLeft())
367 return fa2;
368 if (fa3.isLeft())
369 return fa3;
370 return Right(f(fa1.value, fa2.value, fa3.value));
371 }
372 /**
373 * Maps 4 `Either` values by the mapping function, returning a new
374 * `Either` reference that is a `Right` only if all 4 `Either` values are
375 * `Right` values, otherwise it returns the first `Left` value noticed.
376 *
377 * ```typescript
378 * // Yields Right(10)
379 * Try.map4(Right(1), Right(2), Right(3), Right(4),
380 * (a, b, c, d) => a + b + c + d
381 * )
382 *
383 * // Yields Left, because the second arg is a Left
384 * Try.map4(Right(1), Left("error"), Right(3), Right(4),
385 * (a, b, c, d) => a + b + c + d
386 * )
387 * ```
388 */
389 static map4(fa1, fa2, fa3, fa4, f) {
390 if (fa1.isLeft())
391 return fa1;
392 if (fa2.isLeft())
393 return fa2;
394 if (fa3.isLeft())
395 return fa3;
396 if (fa4.isLeft())
397 return fa4;
398 return Right(f(fa1.value, fa2.value, fa3.value, fa4.value));
399 }
400 /**
401 * Maps 5 `Either` values by the mapping function, returning a new
402 * `Either` reference that is a `Right` only if all 5 `Either` values are
403 * `Right` values, otherwise it returns the first `Left` value noticed.
404 *
405 * ```typescript
406 * // Yields Right(15)
407 * Try.map5(Right(1), Right(2), Right(3), Right(4), Right(5),
408 * (a, b, c, d, e) => a + b + c + d + e
409 * )
410 *
411 * // Yields Left, because the second arg is a Left
412 * Try.map5(Right(1), Left("error"), Right(3), Right(4), Right(5),
413 * (a, b, c, d, e) => a + b + c + d + e
414 * )
415 * ```
416 */
417 static map5(fa1, fa2, fa3, fa4, fa5, f) {
418 if (fa1.isLeft())
419 return fa1;
420 if (fa2.isLeft())
421 return fa2;
422 if (fa3.isLeft())
423 return fa3;
424 if (fa4.isLeft())
425 return fa4;
426 if (fa5.isLeft())
427 return fa5;
428 return Right(f(fa1.value, fa2.value, fa3.value, fa4.value, fa5.value));
429 }
430 /**
431 * Maps 6 `Either` values by the mapping function, returning a new
432 * `Either` reference that is a `Right` only if all 6 `Either` values are
433 * `Right` values, otherwise it returns the first `Left` value noticed.
434 *
435 * ```typescript
436 * // Yields Right(21)
437 * Try.map5(Right(1), Right(2), Right(3), Right(4), Right(5), Right(6),
438 * (a, b, c, d, e, f) => a + b + c + d + e + f
439 * )
440 *
441 * // Yields Left, because the second arg is a Left
442 * Try.map5(Right(1), Left("error"), Right(3), Right(4), Right(5), Right(6),
443 * (a, b, c, d, e, f) => a + b + c + d + e + f
444 * )
445 * ```
446 */
447 static map6(fa1, fa2, fa3, fa4, fa5, fa6, f) {
448 if (fa1.isLeft())
449 return fa1;
450 if (fa2.isLeft())
451 return fa2;
452 if (fa3.isLeft())
453 return fa3;
454 if (fa4.isLeft())
455 return fa4;
456 if (fa5.isLeft())
457 return fa5;
458 if (fa6.isLeft())
459 return fa6;
460 return Right(f(fa1.value, fa2.value, fa3.value, fa4.value, fa5.value, fa6.value));
461 }
462 /**
463 * Keeps calling `f` until a `Right(b)` is returned.
464 *
465 * Based on Phil Freeman's
466 * [Stack Safety for Free]{@link http://functorial.com/stack-safety-for-free/index.pdf}.
467 *
468 * Described in `FlatMap.tailRecM`.
469 */
470 static tailRecM(a, f) {
471 let cursor = a;
472 while (true) {
473 const result = f(cursor);
474 if (!result.isRight())
475 return result;
476 const some = result.value;
477 if (some.isRight())
478 return Right(some.value);
479 cursor = some.value;
480 }
481 }
482}
483/**
484 * Result of the [[Left]] data constructor, representing
485 * "left" values in the [[Either]] disjunction.
486 *
487 * @final
488 */
489export class TLeft extends Either {
490 constructor(value) { super(value, "left"); }
491}
492/**
493 * The `Left` data constructor represents the left side of the
494 * [[Either]] disjoint union, as opposed to the [[Right]] side.
495 */
496export function Left(value) {
497 return new TLeft(value);
498}
499/**
500 * Result of the [[Right]] data constructor, representing
501 * "right" values in the [[Either]] disjunction.
502 *
503 * @final
504 */
505export class TRight extends Either {
506 constructor(value) { super(value, "right"); }
507}
508/**
509 * The `Right` data constructor represents the right side of the
510 * [[Either]] disjoint union, as opposed to the [[Left]] side.
511 */
512export function Right(value) {
513 return new TRight(value);
514}
515/**
516 * Type-class implementations, compatible with the `static-land`
517 * and `funland` specifications.
518 *
519 * See [funland-js.org](https://funland-js.org).
520 */
521export const EitherModule = {
522 // Setoid
523 equals: (x, y) => x ? x.equals(y) : !y,
524 // Functor
525 map: (f, fa) => fa.map(f),
526 // Apply
527 ap: (ff, fa) => fa.ap(ff),
528 // Applicative
529 of: Either.pure,
530 // Chain
531 chain: (f, fa) => fa.flatMap(f),
532 // ChainRec
533 chainRec: (f, a) => Either.tailRecM(a, a => f(Either.left, Either.right, a))
534};
535// Registers Fantasy-Land compatible symbols
536fantasyLandRegister(Either, EitherModule, EitherModule);
537/**
538 * Represents optional values, inspired by Scala's `Option` and by
539 * Haskell's `Maybe` data types.
540 *
541 * Option is an immutable data type, represented as a sum type, being
542 * either a [[Some]], in case it contains a single element, or a [[None]],
543 * in case it is empty.
544 *
545 * The most idiomatic way to use an `Option` instance is to treat it
546 * as a collection or monad and use `map`,`flatMap`, `filter`,
547 * or `forEach`.
548 *
549 * @final
550 */
551export class Option {
552 constructor(ref, isEmpty) {
553 /* tslint:disable-next-line:strict-type-predicates */
554 this._isEmpty = isEmpty != null ? isEmpty : (ref === null || ref === undefined);
555 this.value = ref;
556 }
557 /**
558 * Returns the option's value.
559 *
560 * WARNING!
561 *
562 * This function is partial, the option must be non-empty, otherwise
563 * a runtime exception will get thrown. Use with care.
564 *
565 * @throws [[NoSuchElementError]] in case the option is empty
566 */
567 get() {
568 if (!this._isEmpty)
569 return this.value;
570 throw new NoSuchElementError("Option.get");
571 }
572 /**
573 * Returns the option's value if the option is nonempty, otherwise
574 * return the given `fallback`.
575 *
576 * See [[Option.getOrElseL]] for a lazy alternative.
577 */
578 getOrElse(fallback) {
579 if (!this._isEmpty)
580 return this.value;
581 else
582 return fallback;
583 }
584 /**
585 * Returns the option's value if the option is nonempty, otherwise
586 * return `null`.
587 * ```
588 */
589 orNull() {
590 return !this._isEmpty ? this.value : null;
591 }
592 /**
593 * Returns the option's value if the option is nonempty, otherwise
594 * return `undefined`.
595 */
596 orUndefined() {
597 return !this._isEmpty ? this.value : undefined;
598 }
599 /**
600 * Returns the option's value if the option is nonempty, otherwise
601 * return the result of evaluating `thunk`.
602 *
603 * See [[Option.getOrElse]] for a strict alternative.
604 */
605 getOrElseL(thunk) {
606 if (!this._isEmpty)
607 return this.value;
608 else
609 return thunk();
610 }
611 /**
612 * Returns this option if it is nonempty, otherwise returns the
613 * given `fallback`.
614 */
615 orElse(fallback) {
616 if (!this._isEmpty)
617 return this;
618 else
619 return fallback;
620 }
621 /**
622 * Returns this option if it is nonempty, otherwise returns the
623 * given result of evaluating the given `thunk`.
624 *
625 * @param thunk a no-params function that gets evaluated and
626 * whose result is returned in case this option is empty
627 */
628 orElseL(thunk) {
629 if (!this._isEmpty)
630 return this;
631 else
632 return thunk();
633 }
634 /**
635 * Returns `true` if the option is empty, `false` otherwise.
636 */
637 isEmpty() { return this._isEmpty; }
638 /**
639 * Returns `true` if the option is not empty, `false` otherwise.
640 */
641 nonEmpty() { return !this._isEmpty; }
642 /**
643 * Returns an option containing the result of applying `f` to
644 * this option's value, or an empty option if the source is empty.
645 *
646 * NOTE: this is similar with `flatMap`, except with `map` the
647 * result of `f` doesn't need to be wrapped in an `Option`.
648 *
649 * @param f the mapping function that will transform the value
650 * of this option if nonempty.
651 *
652 * @return a new option instance containing the value of the
653 * source mapped by the given function
654 */
655 map(f) {
656 return this._isEmpty ? None : Some(f(this.value));
657 }
658 /**
659 * Returns the result of applying `f` to this option's value if
660 * the option is nonempty, otherwise returns an empty option.
661 *
662 * NOTE: this is similar with `map`, except that `flatMap` the
663 * result returned by `f` is expected to be boxed in an `Option`
664 * already.
665 *
666 * Example:
667 *
668 * ```typescript
669 * const opt = Option.of(10)
670 *
671 * opt.flatMap(num => {
672 * if (num % 2 == 0)
673 * Some(num + 1)
674 * else
675 * None
676 * })
677 * ```
678 *
679 * @param f the mapping function that will transform the value
680 * of this option if nonempty.
681 *
682 * @return a new option instance containing the value of the
683 * source mapped by the given function
684 */
685 flatMap(f) {
686 if (this._isEmpty)
687 return None;
688 else
689 return f(this.value);
690 }
691 /** Alias for [[flatMap]]. */
692 chain(f) {
693 return this.flatMap(f);
694 }
695 /**
696 * `Applicative` apply operator.
697 *
698 * Resembles {@link map}, but the passed mapping function is
699 * lifted in the `Either` context.
700 */
701 ap(ff) {
702 return ff.flatMap(f => this.map(f));
703 }
704 filter(p) {
705 if (this._isEmpty || !p(this.value))
706 return None;
707 else
708 return this;
709 }
710 /**
711 * Returns the result of applying `f` to this option's value,
712 * or in case the option is empty, the return the result of
713 * evaluating the `fallback` function.
714 *
715 * This function is equivalent with:
716 *
717 * ```typescript
718 * opt.map(f).getOrElseL(fallback)
719 * ```
720 *
721 * @param fallback is the function to be evaluated in case this
722 * option is empty
723 *
724 * @param f is the mapping function for transforming this option's
725 * value in case it is nonempty
726 */
727 fold(fallback, f) {
728 if (this._isEmpty)
729 return fallback();
730 return f(this.value);
731 }
732 /**
733 * Returns true if this option is nonempty and the value it
734 * holds is equal to the given `elem`.
735 */
736 contains(elem) {
737 return !this._isEmpty && std.is(this.value, elem);
738 }
739 /**
740 * Returns `true` if this option is nonempty and the given
741 * predicate returns `true` when applied on this option's value.
742 *
743 * @param p is the predicate function to test
744 */
745 exists(p) {
746 return !this._isEmpty && p(this.value);
747 }
748 /**
749 * Returns true if this option is empty or the given predicate
750 * returns `true` when applied on this option's value.
751 *
752 * @param p is the predicate function to test
753 */
754 forAll(p) {
755 return this._isEmpty || p(this.value);
756 }
757 /**
758 * Apply the given procedure `cb` to the option's value if
759 * this option is nonempty, otherwise do nothing.
760 *
761 * @param cb the procedure to apply
762 */
763 forEach(cb) {
764 if (!this._isEmpty)
765 cb(this.value);
766 }
767 /**
768 * Implements {@link IEquals.equals}.
769 *
770 * @param that is the right hand side of the equality check
771 */
772 equals(that) {
773 // tslint:disable-next-line:strict-type-predicates
774 if (that == null)
775 return false;
776 if (this.nonEmpty() && that.nonEmpty()) {
777 return std.is(this.value, that.value);
778 }
779 return this.isEmpty() && that.isEmpty();
780 }
781 // Implemented from IEquals
782 hashCode() {
783 if (this._isEmpty)
784 return 2433880;
785 else if (this.value == null)
786 return 2433881 << 2;
787 else
788 return std.hashCode(this.value) << 2;
789 }
790 /**
791 * Builds an [[Option]] reference that contains the given value.
792 *
793 * If the given value is `null` or `undefined` then the returned
794 * option will be empty.
795 */
796 static of(value) {
797 return value != null ? Some(value) : None;
798 }
799 /**
800 * Builds an [[Option]] reference that contains the given reference.
801 *
802 * Note that `value` is allowed to be `null` or `undefined`, the
803 * returned option will still be non-empty. Use [[Option.of]]
804 * if you want to avoid this problem. This means:
805 *
806 * ```typescript
807 * const opt = Some<number | null>(null)
808 *
809 * opt.isEmpty()
810 * //=> false
811 *
812 * opt.get()
813 * //=> null
814 * ```
815 */
816 static some(value) {
817 return new Option(value, false);
818 }
819 /**
820 * Returns an empty [[Option]].
821 *
822 * NOTE: Because `Option` is immutable, this function returns the
823 * same cached reference is on different calls.
824 */
825 static none() {
826 return None;
827 }
828 /**
829 * Returns an empty [[Option]].
830 *
831 * Similar to [[Option.none]], but this one allows specifying a
832 * type parameter (in the context of TypeScript or Flow or other
833 * type system).
834 *
835 * NOTE: Because `Option` is immutable, this function returns the
836 * same cached reference is on different calls.
837 */
838 static empty() {
839 return None;
840 }
841 /**
842 * Alias for [[Some]].
843 */
844 static pure(value) { return Some(value); }
845 /**
846 * Maps 2 optional values by the mapping function, returning a new
847 * optional reference that is `Some` only if both option values are
848 * `Some`, otherwise it returns a `None`.
849 *
850 * ```typescript
851 * // Yields Some(3)
852 * Option.map2(Some(1), Some(2),
853 * (a, b) => a + b
854 * )
855 *
856 * // Yields None, because the second arg is None
857 * Option.map2(Some(1), None,
858 * (a, b) => a + b
859 * )
860 * ```
861 *
862 * This operation is the `Applicative.map2`.
863 */
864 static map2(fa1, fa2, f) {
865 return fa1.nonEmpty() && fa2.nonEmpty()
866 ? Some(f(fa1.value, fa2.value))
867 : None;
868 }
869 /**
870 * Maps 3 optional values by the mapping function, returning a new
871 * optional reference that is `Some` only if all 3 option values are
872 * `Some`, otherwise it returns a `None`.
873 *
874 * ```typescript
875 * // Yields Some(6)
876 * Option.map3(Some(1), Some(2), Some(3),
877 * (a, b, c) => a + b + c
878 * )
879 *
880 * // Yields None, because the second arg is None
881 * Option.map3(Some(1), None, Some(3),
882 * (a, b, c) => a + b + c
883 * )
884 * ```
885 */
886 static map3(fa1, fa2, fa3, f) {
887 return fa1.nonEmpty() && fa2.nonEmpty() && fa3.nonEmpty()
888 ? Some(f(fa1.value, fa2.value, fa3.value))
889 : None;
890 }
891 /**
892 * Maps 4 optional values by the mapping function, returning a new
893 * optional reference that is `Some` only if all 4 option values are
894 * `Some`, otherwise it returns a `None`.
895 *
896 * ```typescript
897 * // Yields Some(10)
898 * Option.map4(Some(1), Some(2), Some(3), Some(4),
899 * (a, b, c, d) => a + b + c + d
900 * )
901 *
902 * // Yields None, because the second arg is None
903 * Option.map4(Some(1), None, Some(3), Some(4),
904 * (a, b, c, d) => a + b + c + d
905 * )
906 * ```
907 */
908 static map4(fa1, fa2, fa3, fa4, f) {
909 return fa1.nonEmpty() && fa2.nonEmpty() && fa3.nonEmpty() && fa4.nonEmpty()
910 ? Some(f(fa1.value, fa2.value, fa3.value, fa4.value))
911 : None;
912 }
913 /**
914 * Maps 5 optional values by the mapping function, returning a new
915 * optional reference that is `Some` only if all 5 option values are
916 * `Some`, otherwise it returns a `None`.
917 *
918 * ```typescript
919 * // Yields Some(15)
920 * Option.map5(Some(1), Some(2), Some(3), Some(4), Some(5),
921 * (a, b, c, d, e) => a + b + c + d + e
922 * )
923 *
924 * // Yields None, because the second arg is None
925 * Option.map5(Some(1), None, Some(3), Some(4), Some(5),
926 * (a, b, c, d, e) => a + b + c + d + e
927 * )
928 * ```
929 */
930 static map5(fa1, fa2, fa3, fa4, fa5, f) {
931 return fa1.nonEmpty() && fa2.nonEmpty() && fa3.nonEmpty() && fa4.nonEmpty() && fa5.nonEmpty()
932 ? Some(f(fa1.value, fa2.value, fa3.value, fa4.value, fa5.value))
933 : None;
934 }
935 /**
936 * Maps 6 optional values by the mapping function, returning a new
937 * optional reference that is `Some` only if all 6 option values are
938 * `Some`, otherwise it returns a `None`.
939 *
940 * ```typescript
941 * // Yields Some(21)
942 * Option.map6(Some(1), Some(2), Some(3), Some(4), Some(5), Some(6),
943 * (a, b, c, d, e, f) => a + b + c + d + e + f
944 * )
945 *
946 * // Yields None, because the second arg is None
947 * Option.map6(Some(1), None, Some(3), Some(4), Some(5), Some(6),
948 * (a, b, c, d, e, f) => a + b + c + d + e + f
949 * )
950 * ```
951 */
952 static map6(fa1, fa2, fa3, fa4, fa5, fa6, f) {
953 return fa1.nonEmpty() && fa2.nonEmpty() && fa3.nonEmpty() && fa4.nonEmpty() && fa5.nonEmpty() && fa6.nonEmpty()
954 ? Some(f(fa1.value, fa2.value, fa3.value, fa4.value, fa5.value, fa6.value))
955 : None;
956 }
957 /**
958 * Keeps calling `f` until a `Right(b)` is returned.
959 *
960 * Based on Phil Freeman's
961 * [Stack Safety for Free]{@link http://functorial.com/stack-safety-for-free/index.pdf}.
962 *
963 * Described in `FlatMap.tailRecM`.
964 */
965 static tailRecM(a, f) {
966 let cursor = a;
967 while (true) {
968 const result = f(cursor);
969 if (result.nonEmpty()) {
970 const some = result.value;
971 if (some.isRight())
972 return Some(some.value);
973 cursor = some.value;
974 }
975 else {
976 return None;
977 }
978 }
979 }
980}
981/**
982 * Result of the [[Some]] data constructor, representing
983 * non-empty values in the [[Option]] disjunction.
984 */
985export class TSome extends Option {
986 constructor(value) { super(value, false); }
987}
988/**
989 * The `Some<A>` data constructor for [[Option]] represents existing
990 * values of type `A`.
991 *
992 * Using this function is equivalent with [[Option.some]].
993 */
994export function Some(value) {
995 return new TSome(value);
996}
997/**
998 * Result of the [[Some]] data constructor, representing
999 * non-empty values in the [[Option]] disjunction.
1000 */
1001export class TNone extends Option {
1002 constructor() { super(undefined, true); }
1003}
1004/**
1005 * The `None` data constructor for [[Option]] represents non-existing
1006 * values for any type.
1007 *
1008 * Using this reference directly is equivalent with [[Option.none]].
1009 */
1010export const None = new TNone();
1011/**
1012 * Type-class implementations, compatible with the `static-land`
1013 * and `funland` specification.
1014 *
1015 * See [funland-js.org](https://funland-js.org).
1016 */
1017export const OptionModule = {
1018 // Setoid
1019 equals: (x, y) => x ? x.equals(y) : !y,
1020 // Functor
1021 map: (f, fa) => fa.map(f),
1022 // Apply
1023 ap: (ff, fa) => fa.ap(ff),
1024 // Applicative
1025 of: Option.pure,
1026 // Chain
1027 chain: (f, fa) => fa.flatMap(f),
1028 // ChainRec
1029 chainRec: (f, a) => Option.tailRecM(a, a => f(Either.left, Either.right, a))
1030};
1031// Registers Fantasy-Land compatible symbols
1032fantasyLandRegister(Option, OptionModule, OptionModule);
1033/**
1034 * The `Try` type represents a computation that may either result in an
1035 * exception, or return a successfully computed value. It's similar to,
1036 * but semantically different from the [[Either]] type.
1037 *
1038 * `Try` is a sum type and so instances of `Try` are either instances
1039 * of [[Success]] or of [[Failure]].
1040 *
1041 * For example, `Try` can be used to perform division on a user-defined
1042 * input, without the need to do explicit exception-handling in all of
1043 * the places that an exception might occur.
1044 *
1045 * Example:
1046 *
1047 * ```typescript
1048 * function divide(dividendS: string, divisorS: string): string {
1049 * const dividend = Try(() => parseInt(dividendS))
1050 * .filter(_ => _ === _) // filter out NaN
1051 * const divisor = Try(() => parseInt(divisorS))
1052 * .filter(_ => _ === _) // filter out NaN
1053 *
1054 * // map2 executes the given function only if both results are
1055 * // successful; we could also express this with flatMap / chain
1056 * const result = Try.map2(dividend, divisor,
1057 * (a, b) => a / b
1058 * )
1059 *
1060 * result.fold(
1061 * error => `failure: ${error}`
1062 * result => `result: ${result}`
1063 * )
1064 * }
1065 * ```
1066 *
1067 * An important property of `Try` is its ability to pipeline, or chain,
1068 * operations, catching exceptions along the way. The `flatMap` and `map`
1069 * combinators each essentially pass off either their successfully completed
1070 * value, wrapped in the [[Success]] type for it to be further operated upon
1071 * by the next combinator in the chain, or the exception wrapped in the
1072 * [[Failure]] type usually to be simply passed on down the chain.
1073 * Combinators such as `recover` and `recoverWith` are designed to provide
1074 * some type of global behavior in the case of failure.
1075 *
1076 * NOTE: all `Try` combinators will catch exceptions and return failure
1077 * unless otherwise specified in the documentation.
1078 */
1079export class Try {
1080 constructor(value, tag) {
1081 this._isSuccess = tag === "success";
1082 this.value = value;
1083 }
1084 /**
1085 * Returns `true` if the source is a [[Success]] result,
1086 * or `false` in case it is a [[Failure]].
1087 */
1088 isSuccess() { return this._isSuccess; }
1089 /**
1090 * Returns `true` if the source is a [[Failure]],
1091 * or `false` in case it is a [[Success]] result.
1092 */
1093 isFailure() { return !this._isSuccess; }
1094 /**
1095 * Returns a Try's successful value if it's a [[Success]] reference,
1096 * otherwise throws an exception if it's a [[Failure]].
1097 *
1098 * WARNING!
1099 *
1100 * This function is partial, the option must be non-empty, otherwise
1101 * a runtime exception will get thrown. Use with care.
1102 */
1103 get() {
1104 if (!this._isSuccess)
1105 throw this.value;
1106 return this.value;
1107 }
1108 /**
1109 * Returns the value from a `Success` or the given `fallback`
1110 * value if this is a `Failure`.
1111 *
1112 * ```typescript
1113 * Success(10).getOrElse(27) // 10
1114 * Failure("error").getOrElse(27) // 27
1115 * ```
1116 */
1117 getOrElse(fallback) {
1118 return this._isSuccess ? this.value : fallback;
1119 }
1120 /**
1121 * Returns the value from a `Success` or the value generated
1122 * by a given `thunk` in case this is a `Failure`.
1123 *
1124 * ```typescript
1125 * Success(10).getOrElseL(() => 27) // 10
1126 * Failure("error").getOrElseL(() => 27) // 27
1127 * ```
1128 */
1129 getOrElseL(thunk) {
1130 return this._isSuccess ? this.value : thunk();
1131 }
1132 /**
1133 * Returns the current value if it's a [[Success]], or
1134 * if the source is a [[Failure]] then return `null`.
1135 *
1136 * ```typescript
1137 * Success(10).orNull() // 10
1138 * Failure("error").orNull() // null
1139 * ```
1140 *
1141 * This can be useful for use-cases such as:
1142 *
1143 * ```typescript
1144 * Try.of(() => dict.user.profile.name).orNull()
1145 * ```
1146 */
1147 orNull() {
1148 return this._isSuccess ? this.value : null;
1149 }
1150 /**
1151 * Returns the current value if it's a [[Success]], or
1152 * if the source is a [[Failure]] then return `undefined`.
1153 *
1154 * ```typescript
1155 * Success(10).orUndefined() // 10
1156 * Failure("error").orUndefined() // undefined
1157 * ```
1158 *
1159 * This can be useful for use-cases such as:
1160 *
1161 * ```typescript
1162 * Try.of(() => dict.user.profile.name).orUndefined()
1163 * ```
1164 */
1165 orUndefined() {
1166 return this._isSuccess ? this.value : undefined;
1167 }
1168 /**
1169 * Returns the current value if it's a [[Success]], or if
1170 * the source is a [[Failure]] then return the `fallback`.
1171 *
1172 * ```typescript
1173 * Success(10).orElse(Success(17)) // 10
1174 * Failure("error").orElse(Success(17)) // 17
1175 * ```
1176 */
1177 orElse(fallback) {
1178 if (this._isSuccess)
1179 return this;
1180 return fallback;
1181 }
1182 /**
1183 * Returns the current value if it's a [[Success]], or if the source
1184 * is a [[Failure]] then return the value generated by the given
1185 * `thunk`.
1186 *
1187 * ```typescript
1188 * Success(10).orElseL(() => Success(17)) // 10
1189 * Failure("error").orElseL(() => Success(17)) // 17
1190 * ```
1191 */
1192 orElseL(thunk) {
1193 if (this._isSuccess)
1194 return this;
1195 return thunk();
1196 }
1197 /**
1198 * Inverts this `Try`. If this is a [[Failure]], returns its exception wrapped
1199 * in a [[Success]]. If this is a `Success`, returns a `Failure` containing a
1200 * [[NoSuchElementError]].
1201 */
1202 failed() {
1203 return this._isSuccess
1204 ? Failure(new NoSuchElementError("try.failed()"))
1205 : Success(this.value);
1206 }
1207 /**
1208 * Applies the `failure` function to [[Failure]] values, and the
1209 * `success` function to [[Success]] values and returns the result.
1210 *
1211 * ```typescript
1212 * const maybeNum: Try<number> =
1213 * tryParseInt("not a number")
1214 *
1215 * const result: string =
1216 * maybeNum.fold(
1217 * error => `Could not parse string: ${error}`,
1218 * num => `Success: ${num}`
1219 * )
1220 * ```
1221 */
1222 fold(failure, success) {
1223 return this._isSuccess
1224 ? success(this.value)
1225 : failure(this.value);
1226 }
1227 filter(p) {
1228 if (!this._isSuccess)
1229 return this;
1230 try {
1231 if (p(this.value))
1232 return this;
1233 return Failure(new NoSuchElementError(`Predicate does not hold for ${this.value}`));
1234 }
1235 catch (e) {
1236 return Failure(e);
1237 }
1238 }
1239 /**
1240 * Returns the given function applied to the value if this is
1241 * a [[Success]] or returns `this` if this is a [[Failure]].
1242 *
1243 * This operation is the monadic "bind" operation.
1244 * It can be used to *chain* multiple `Try` references.
1245 *
1246 * ```typescript
1247 * Try.of(() => parse(s1)).flatMap(num1 =>
1248 * Try.of(() => parse(s2)).map(num2 =>
1249 * num1 / num2
1250 * ))
1251 * ```
1252 */
1253 flatMap(f) {
1254 if (!this._isSuccess)
1255 return this;
1256 try {
1257 return f(this.value);
1258 }
1259 catch (e) {
1260 return Failure(e);
1261 }
1262 }
1263 /** Alias for [[flatMap]]. */
1264 chain(f) {
1265 return this.flatMap(f);
1266 }
1267 /**
1268 * `Applicative` apply operator.
1269 *
1270 * Resembles {@link map}, but the passed mapping function is
1271 * lifted in the `Either` context.
1272 */
1273 ap(ff) {
1274 return ff.flatMap(f => this.map(f));
1275 }
1276 /**
1277 * Returns a `Try` containing the result of applying `f` to
1278 * this option's value, but only if it's a `Success`, or
1279 * returns the current `Failure` without any modifications.
1280 *
1281 * NOTE: this is similar with `flatMap`, except with `map` the
1282 * result of `f` doesn't need to be wrapped in a `Try`.
1283 *
1284 * @param f the mapping function that will transform the value
1285 * of this `Try` if successful.
1286 *
1287 * @return a new `Try` instance containing the value of the
1288 * source mapped by the given function
1289 */
1290 map(f) {
1291 return this._isSuccess
1292 ? Try.of(() => f(this.value))
1293 : this;
1294 }
1295 /**
1296 * Applies the given function `cb` if this is a [[Success]], otherwise
1297 * returns `void` if this is a [[Failure]].
1298 */
1299 forEach(cb) {
1300 if (this._isSuccess)
1301 cb(this.value);
1302 }
1303 /**
1304 * Applies the given function `f` if this is a `Failure`, otherwise
1305 * returns `this` if this is a `Success`.
1306 *
1307 * This is like `map` for the exception.
1308 *
1309 * In the following example, if the `user.profile.email` exists,
1310 * then it is returned as a successful value, otherwise
1311 *
1312 * ```typescript
1313 * Try.of(() => user.profile.email).recover(e => {
1314 * // Access error? Default to empty.
1315 * if (e instanceof TypeError) return ""
1316 * throw e // We don't know what it is, rethrow
1317 * })
1318 *
1319 * Note that on rethrow, the error is being caught in `recover` and
1320 * it still returns it as a `Failure(e)`.
1321 * ```
1322 */
1323 recover(f) {
1324 return this._isSuccess
1325 ? this
1326 : Try.of(() => f(this.value));
1327 }
1328 /**
1329 * Applies the given function `f` if this is a `Failure`, otherwise
1330 * returns `this` if this is a `Success`.
1331 *
1332 * This is like `map` for the exception.
1333 *
1334 * In the following example, if the `user.profile.email` exists,
1335 * then it is returned as a successful value, otherwise
1336 *
1337 * ```typescript
1338 * Try.of(() => user.profile.email).recover(e => {
1339 * // Access error? Default to empty.
1340 * if (e instanceof TypeError) return ""
1341 * throw e // We don't know what it is, rethrow
1342 * })
1343 *
1344 * Note that on rethrow, the error is being caught in `recover` and
1345 * it still returns it as a `Failure(e)`.
1346 * ```
1347 */
1348 recoverWith(f) {
1349 try {
1350 return this._isSuccess ? this : f(this.value);
1351 }
1352 catch (e) {
1353 return Failure(e);
1354 }
1355 }
1356 /**
1357 * Transforms the source into an [[Option]].
1358 *
1359 * In case the source is a `Success(v)`, then it gets translated
1360 * into a `Some(v)`. If the source is a `Failure(e)`, then a `None`
1361 * value is returned.
1362 *
1363 * ```typescript
1364 * Success("value").toOption() // Some("value")
1365 * Failure("error").toOption() // None
1366 * ```
1367 */
1368 toOption() {
1369 return this._isSuccess ? Some(this.value) : None;
1370 }
1371 /**
1372 * Transforms the source into an [[Either]].
1373 *
1374 * In case the source is a `Success(v)`, then it gets translated
1375 * into a `Right(v)`. If the source is a `Failure(e)`, then a `Left(e)`
1376 * value is returned.
1377 *
1378 * ```typescript
1379 * Success("value").toEither() // Right("value")
1380 * Failure("error").toEither() // Left("error")
1381 * ```
1382 */
1383 toEither() {
1384 return this._isSuccess
1385 ? Right(this.value)
1386 : Left(this.value);
1387 }
1388 /**
1389 * Implements {@link IEquals.equals} with overridable equality for `A`.
1390 */
1391 equals(that) {
1392 // tslint:disable-next-line:strict-type-predicates
1393 if (that == null)
1394 return false;
1395 return this._isSuccess
1396 ? that._isSuccess && std.is(this.value, that.value)
1397 : !that._isSuccess && std.is(this.value, that.value);
1398 }
1399 // Implemented from IEquals
1400 hashCode() {
1401 return this._isSuccess
1402 ? std.hashCode(this.value)
1403 : std.hashCode(this.value);
1404 }
1405 /**
1406 * Evaluates the given `thunk` and returns either a [[Success]],
1407 * in case the evaluation succeeded, or a [[Failure]], in case
1408 * an exception was thrown.
1409 *
1410 * Example:
1411 *
1412 * ```typescript
1413 * let effect = 0
1414 *
1415 * const e = Try.of(() => { effect += 1; return effect })
1416 * e.get() // 1
1417 * ```
1418 */
1419 static of(thunk) {
1420 try {
1421 return Success(thunk());
1422 }
1423 catch (e) {
1424 return Failure(e);
1425 }
1426 }
1427 /** Alias of [[Try.success]]. */
1428 static pure(value) {
1429 return Try.success(value);
1430 }
1431 /**
1432 * Shorthand for `now(undefined as void)`, always returning
1433 * the same reference as optimization.
1434 */
1435 static unit() {
1436 return tryUnitRef;
1437 }
1438 /**
1439 * Returns a [[Try]] reference that represents a successful result
1440 * (i.e. wrapped in [[Success]]).
1441 */
1442 static success(value) {
1443 return Success(value);
1444 }
1445 /**
1446 * Returns a [[Try]] reference that represents a failure
1447 * (i.e. an exception wrapped in [[Failure]]).
1448 */
1449 static failure(e) {
1450 return Failure(e);
1451 }
1452 /**
1453 * Alias for {@link Try.failure} and {@link Failure},
1454 * wrapping any throwable into a `Try` value.
1455 */
1456 static raise(e) {
1457 return Failure(e);
1458 }
1459 /**
1460 * Maps 2 `Try` values by the mapping function, returning a new
1461 * `Try` reference that is a `Success` only if both `Try` values are
1462 * a `Success`, otherwise it returns the first `Failure` noticed.
1463 *
1464 * ```typescript
1465 * // Yields Success(3)
1466 * Try.map2(Success(1), Success(2),
1467 * (a, b) => a + b
1468 * )
1469 *
1470 * // Yields Failure, because the second arg is a Failure
1471 * Try.map2(Success(1), Failure("error"),
1472 * (a, b) => a + b
1473 * )
1474 * ```
1475 *
1476 * This operation is the `Applicative.map2`.
1477 */
1478 static map2(fa1, fa2, f) {
1479 if (fa1.isFailure())
1480 return fa1;
1481 if (fa2.isFailure())
1482 return fa2;
1483 try {
1484 return Success(f(fa1.value, fa2.value));
1485 }
1486 catch (e) {
1487 return Failure(e);
1488 }
1489 }
1490 /**
1491 * Maps 3 `Try` values by the mapping function, returning a new
1492 * `Try` reference that is a `Success` only if all 3 `Try` values are
1493 * a `Success`, otherwise it returns the first `Failure` noticed.
1494 *
1495 * ```typescript
1496 * // Yields Success(6)
1497 * Try.map3(Success(1), Success(2), Success(3),
1498 * (a, b, c) => {
1499 * return a + b + c
1500 * }
1501 * )
1502 *
1503 * // Yields Failure, because the second arg is a Failure
1504 * Try.map3(
1505 * Success(1),
1506 * Failure("error"),
1507 * Success(3),
1508 *
1509 * (a, b, c) => {
1510 * return a + b + c
1511 * }
1512 * )
1513 * ```
1514 */
1515 static map3(fa1, fa2, fa3, f) {
1516 if (fa1.isFailure())
1517 return fa1;
1518 if (fa2.isFailure())
1519 return fa2;
1520 if (fa3.isFailure())
1521 return fa3;
1522 try {
1523 return Success(f(fa1.value, fa2.value, fa3.value));
1524 }
1525 catch (e) {
1526 return Failure(e);
1527 }
1528 }
1529 /**
1530 * Maps 4 `Try` values by the mapping function, returning a new
1531 * `Try` reference that is a `Success` only if all 4 `Try` values are
1532 * a `Success`, otherwise it returns the first `Failure` noticed.
1533 *
1534 * ```typescript
1535 * // Yields Success(10)
1536 * Try.map4(Success(1), Success(2), Success(3), Success(4),
1537 * (a, b, c, d) => {
1538 * return a + b + c + d
1539 * }
1540 * )
1541 *
1542 * // Yields Failure, because the second arg is a Failure
1543 * Try.map3(
1544 * Success(1),
1545 * Failure("error"),
1546 * Success(3),
1547 * Success(4),
1548 *
1549 * (a, b, c, d) => {
1550 * return a + b + c + d
1551 * }
1552 * )
1553 * ```
1554 */
1555 static map4(fa1, fa2, fa3, fa4, f) {
1556 if (fa1.isFailure())
1557 return fa1;
1558 if (fa2.isFailure())
1559 return fa2;
1560 if (fa3.isFailure())
1561 return fa3;
1562 if (fa4.isFailure())
1563 return fa4;
1564 try {
1565 return Success(f(fa1.value, fa2.value, fa3.value, fa4.value));
1566 }
1567 catch (e) {
1568 return Failure(e);
1569 }
1570 }
1571 /**
1572 * Maps 5 `Try` values by the mapping function, returning a new
1573 * `Try` reference that is a `Success` only if all 5 `Try` values are
1574 * a `Success`, otherwise it returns the first `Failure` noticed.
1575 *
1576 * ```typescript
1577 * // Yields Success(15)
1578 * Try.map5(
1579 * Success(1),
1580 * Success(2),
1581 * Success(3),
1582 * Success(4),
1583 * Success(5),
1584 *
1585 * (a, b, c, d, e) => {
1586 * return a + b + c + d + e
1587 * }
1588 * )
1589 *
1590 * // Yields Failure, because the second arg is a Failure
1591 * Try.map5(
1592 * Success(1),
1593 * Failure("error"),
1594 * Success(3),
1595 * Success(4),
1596 * Success(5),
1597 *
1598 * (a, b, c, d, e) => {
1599 * return a + b + c + d + e
1600 * }
1601 * )
1602 * ```
1603 */
1604 static map5(fa1, fa2, fa3, fa4, fa5, f) {
1605 if (fa1.isFailure())
1606 return fa1;
1607 if (fa2.isFailure())
1608 return fa2;
1609 if (fa3.isFailure())
1610 return fa3;
1611 if (fa4.isFailure())
1612 return fa4;
1613 if (fa5.isFailure())
1614 return fa5;
1615 try {
1616 return Success(f(fa1.value, fa2.value, fa3.value, fa4.value, fa5.value));
1617 }
1618 catch (e) {
1619 return Failure(e);
1620 }
1621 }
1622 /**
1623 * Maps 6 `Try` values by the mapping function, returning a new
1624 * `Try` reference that is a `Success` only if all 6 `Try` values are
1625 * a `Success`, otherwise it returns the first `Failure` noticed.
1626 *
1627 * ```typescript
1628 * // Yields Success(21)
1629 * Try.map6(
1630 * Success(1),
1631 * Success(2),
1632 * Success(3),
1633 * Success(4),
1634 * Success(5),
1635 * Success(6),
1636 *
1637 * (a, b, c, d, e, f) => {
1638 * return a + b + c + d + e + f
1639 * }
1640 * )
1641 *
1642 * // Yields Failure, because the second arg is a Failure
1643 * Try.map6(
1644 * Success(1),
1645 * Failure("error"),
1646 * Success(3),
1647 * Success(4),
1648 * Success(5),
1649 * Success(6),
1650 *
1651 * (a, b, c, d, e, f) => {
1652 * return a + b + c + d + e + f
1653 * }
1654 * )
1655 * ```
1656 */
1657 static map6(fa1, fa2, fa3, fa4, fa5, fa6, f) {
1658 if (fa1.isFailure())
1659 return fa1;
1660 if (fa2.isFailure())
1661 return fa2;
1662 if (fa3.isFailure())
1663 return fa3;
1664 if (fa4.isFailure())
1665 return fa4;
1666 if (fa5.isFailure())
1667 return fa5;
1668 if (fa6.isFailure())
1669 return fa6;
1670 try {
1671 return Success(f(fa1.value, fa2.value, fa3.value, fa4.value, fa5.value, fa6.value));
1672 }
1673 catch (e) {
1674 return Failure(e);
1675 }
1676 }
1677 /**
1678 * Keeps calling `f` until a `Right(b)` is returned.
1679 *
1680 * Based on Phil Freeman's
1681 * [Stack Safety for Free]{@link http://functorial.com/stack-safety-for-free/index.pdf}.
1682 *
1683 * Described in `FlatMap.tailRecM`.
1684 */
1685 static tailRecM(a, f) {
1686 let cursor = a;
1687 while (true) {
1688 try {
1689 const result = f(cursor);
1690 if (result.isFailure())
1691 return result;
1692 const some = result.get();
1693 if (some.isRight())
1694 return Success(some.value);
1695 cursor = some.value;
1696 }
1697 catch (e) {
1698 return Failure(e);
1699 }
1700 }
1701 }
1702}
1703/**
1704 * Result of the [[Success]] data constructor, representing
1705 * successful values in the [[Try]] disjunction.
1706 *
1707 * @final
1708 */
1709export class TSuccess extends Try {
1710 constructor(value) { super(value, "success"); }
1711}
1712/**
1713 * The `Success` data constructor is for building [[Try]] values that
1714 * are successful results of computations, as opposed to [[Failure]].
1715 */
1716export function Success(value) {
1717 return new TSuccess(value);
1718}
1719/**
1720 * The `Success` data constructor is for building [[Try]] values that
1721 * are successful results of computations, as opposed to [[Failure]].
1722 *
1723 * @final
1724 */
1725export class TFailure extends Try {
1726 constructor(value) { super(value, "failure"); }
1727}
1728/**
1729 * The `Failure` data constructor is for building [[Try]] values that
1730 * represent failures, as opposed to [[Success]].
1731 */
1732export function Failure(e) {
1733 return new TFailure(e);
1734}
1735/**
1736 * Type-class implementations, compatible with the `static-land`
1737 * and `funland` specifications.
1738 *
1739 * See [funland-js.org](https://funland-js.org).
1740 */
1741export const TryModule = {
1742 // Setoid
1743 equals: (x, y) => x ? x.equals(y) : !y,
1744 // Functor
1745 map: (f, fa) => fa.map(f),
1746 // Apply
1747 ap: (ff, fa) => fa.ap(ff),
1748 // Applicative
1749 of: Try.pure,
1750 // Chain
1751 chain: (f, fa) => fa.flatMap(f),
1752 // ChainRec
1753 chainRec: (f, a) => Try.tailRecM(a, a => f(Either.left, Either.right, a))
1754};
1755// Registers Fantasy-Land compatible symbols
1756fantasyLandRegister(Try, TryModule, TryModule);
1757/**
1758 * Reusable reference, to use in {@link Try.unit}.
1759 *
1760 * @private
1761 * @hidden
1762 */
1763const tryUnitRef = Success(undefined);
1764//# sourceMappingURL=disjunctions.js.map
\No newline at end of file