版博士V2.0程序
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 

664 строки
18 KiB

  1. import { fromEquals } from './Eq';
  2. import { fromOption as fromOption_, fromOptionK as fromOptionK_, fromPredicate as fromPredicate_ } from './FromEither';
  3. import { identity, pipe } from './function';
  4. import { flap as flap_ } from './Functor';
  5. import * as _ from './internal';
  6. // -------------------------------------------------------------------------------------
  7. // refinements
  8. // -------------------------------------------------------------------------------------
  9. /**
  10. * Returns `true` if the these is an instance of `Left`, `false` otherwise
  11. *
  12. * @category refinements
  13. * @since 2.0.0
  14. */
  15. export var isLeft = function (fa) { return fa._tag === 'Left'; };
  16. /**
  17. * Returns `true` if the these is an instance of `Right`, `false` otherwise
  18. *
  19. * @category refinements
  20. * @since 2.0.0
  21. */
  22. export var isRight = function (fa) { return fa._tag === 'Right'; };
  23. /**
  24. * Returns `true` if the these is an instance of `Both`, `false` otherwise
  25. *
  26. * @category refinements
  27. * @since 2.0.0
  28. */
  29. export function isBoth(fa) {
  30. return fa._tag === 'Both';
  31. }
  32. // -------------------------------------------------------------------------------------
  33. // constructors
  34. // -------------------------------------------------------------------------------------
  35. /**
  36. * @category constructors
  37. * @since 2.0.0
  38. */
  39. export function left(left) {
  40. return { _tag: 'Left', left: left };
  41. }
  42. /**
  43. * @category constructors
  44. * @since 2.0.0
  45. */
  46. export function right(right) {
  47. return { _tag: 'Right', right: right };
  48. }
  49. /**
  50. * @category constructors
  51. * @since 2.0.0
  52. */
  53. export function both(left, right) {
  54. return { _tag: 'Both', left: left, right: right };
  55. }
  56. /**
  57. * Less strict version of [`match`](#match).
  58. *
  59. * The `W` suffix (short for **W**idening) means that the handler return types will be merged.
  60. *
  61. * @category pattern matching
  62. * @since 2.10.0
  63. */
  64. export var matchW = function (onLeft, onRight, onBoth) {
  65. return function (fa) {
  66. switch (fa._tag) {
  67. case 'Left':
  68. return onLeft(fa.left);
  69. case 'Right':
  70. return onRight(fa.right);
  71. case 'Both':
  72. return onBoth(fa.left, fa.right);
  73. }
  74. };
  75. };
  76. /**
  77. * Alias of [`matchW`](#matchw).
  78. *
  79. * @category pattern matching
  80. * @since 2.10.0
  81. */
  82. export var foldW = matchW;
  83. /**
  84. * @category pattern matching
  85. * @since 2.10.0
  86. */
  87. export var match = matchW;
  88. /**
  89. * Alias of [`match`](#match).
  90. *
  91. * @category pattern matching
  92. * @since 2.0.0
  93. */
  94. export var fold = match;
  95. /**
  96. * @since 2.4.0
  97. */
  98. export var swap = match(right, left, function (e, a) { return both(a, e); });
  99. /**
  100. * @category instances
  101. * @since 2.0.0
  102. */
  103. export function getShow(SE, SA) {
  104. return {
  105. show: match(function (l) { return "left(".concat(SE.show(l), ")"); }, function (a) { return "right(".concat(SA.show(a), ")"); }, function (l, a) { return "both(".concat(SE.show(l), ", ").concat(SA.show(a), ")"); })
  106. };
  107. }
  108. /**
  109. * @category instances
  110. * @since 2.0.0
  111. */
  112. export function getEq(EE, EA) {
  113. return fromEquals(function (x, y) {
  114. return isLeft(x)
  115. ? isLeft(y) && EE.equals(x.left, y.left)
  116. : isRight(x)
  117. ? isRight(y) && EA.equals(x.right, y.right)
  118. : isBoth(y) && EE.equals(x.left, y.left) && EA.equals(x.right, y.right);
  119. });
  120. }
  121. /**
  122. * @category instances
  123. * @since 2.0.0
  124. */
  125. export function getSemigroup(SE, SA) {
  126. return {
  127. concat: function (x, y) {
  128. return isLeft(x)
  129. ? isLeft(y)
  130. ? left(SE.concat(x.left, y.left))
  131. : isRight(y)
  132. ? both(x.left, y.right)
  133. : both(SE.concat(x.left, y.left), y.right)
  134. : isRight(x)
  135. ? isLeft(y)
  136. ? both(y.left, x.right)
  137. : isRight(y)
  138. ? right(SA.concat(x.right, y.right))
  139. : both(y.left, SA.concat(x.right, y.right))
  140. : isLeft(y)
  141. ? both(SE.concat(x.left, y.left), x.right)
  142. : isRight(y)
  143. ? both(x.left, SA.concat(x.right, y.right))
  144. : both(SE.concat(x.left, y.left), SA.concat(x.right, y.right));
  145. }
  146. };
  147. }
  148. /**
  149. * @category instances
  150. * @since 2.10.0
  151. */
  152. export var getApply = function (S) { return ({
  153. URI: URI,
  154. _E: undefined,
  155. map: _map,
  156. ap: function (fab, fa) {
  157. return isLeft(fab)
  158. ? isLeft(fa)
  159. ? left(S.concat(fab.left, fa.left))
  160. : isRight(fa)
  161. ? left(fab.left)
  162. : left(S.concat(fab.left, fa.left))
  163. : isRight(fab)
  164. ? isLeft(fa)
  165. ? left(fa.left)
  166. : isRight(fa)
  167. ? right(fab.right(fa.right))
  168. : both(fa.left, fab.right(fa.right))
  169. : isLeft(fa)
  170. ? left(S.concat(fab.left, fa.left))
  171. : isRight(fa)
  172. ? both(fab.left, fab.right(fa.right))
  173. : both(S.concat(fab.left, fa.left), fab.right(fa.right));
  174. }
  175. }); };
  176. /**
  177. * @category instances
  178. * @since 2.7.0
  179. */
  180. export function getApplicative(S) {
  181. var A = getApply(S);
  182. return {
  183. URI: URI,
  184. _E: undefined,
  185. map: _map,
  186. ap: A.ap,
  187. of: of
  188. };
  189. }
  190. /**
  191. * @category instances
  192. * @since 2.10.0
  193. */
  194. export function getChain(S) {
  195. var A = getApply(S);
  196. var chain = function (ma, f) {
  197. if (isLeft(ma)) {
  198. return ma;
  199. }
  200. if (isRight(ma)) {
  201. return f(ma.right);
  202. }
  203. var fb = f(ma.right);
  204. return isLeft(fb)
  205. ? left(S.concat(ma.left, fb.left))
  206. : isRight(fb)
  207. ? both(ma.left, fb.right)
  208. : both(S.concat(ma.left, fb.left), fb.right);
  209. };
  210. return {
  211. URI: URI,
  212. _E: undefined,
  213. map: _map,
  214. ap: A.ap,
  215. chain: chain
  216. };
  217. }
  218. /**
  219. * @category instances
  220. * @since 2.0.0
  221. */
  222. export function getMonad(S) {
  223. var C = getChain(S);
  224. return {
  225. URI: URI,
  226. _E: undefined,
  227. map: _map,
  228. of: of,
  229. ap: C.ap,
  230. chain: C.chain,
  231. throwError: left
  232. };
  233. }
  234. /**
  235. * Returns an `E` value if possible
  236. *
  237. * @example
  238. * import { getLeft, left, right, both } from 'fp-ts/These'
  239. * import { none, some } from 'fp-ts/Option'
  240. *
  241. * assert.deepStrictEqual(getLeft(left('a')), some('a'))
  242. * assert.deepStrictEqual(getLeft(right(1)), none)
  243. * assert.deepStrictEqual(getLeft(both('a', 1)), some('a'))
  244. *
  245. * @category conversions
  246. * @since 2.0.0
  247. */
  248. export function getLeft(fa) {
  249. return isLeft(fa) ? _.some(fa.left) : isRight(fa) ? _.none : _.some(fa.left);
  250. }
  251. /**
  252. * Returns an `A` value if possible
  253. *
  254. * @example
  255. * import { getRight, left, right, both } from 'fp-ts/These'
  256. * import { none, some } from 'fp-ts/Option'
  257. *
  258. * assert.deepStrictEqual(getRight(left('a')), none)
  259. * assert.deepStrictEqual(getRight(right(1)), some(1))
  260. * assert.deepStrictEqual(getRight(both('a', 1)), some(1))
  261. *
  262. * @category conversions
  263. * @since 2.0.0
  264. */
  265. export function getRight(fa) {
  266. return isLeft(fa) ? _.none : isRight(fa) ? _.some(fa.right) : _.some(fa.right);
  267. }
  268. // TODO: make lazy in v3
  269. /**
  270. * @example
  271. * import { leftOrBoth, left, both } from 'fp-ts/These'
  272. * import { none, some } from 'fp-ts/Option'
  273. *
  274. * assert.deepStrictEqual(leftOrBoth('a')(none), left('a'))
  275. * assert.deepStrictEqual(leftOrBoth('a')(some(1)), both('a', 1))
  276. *
  277. * @category constructors
  278. * @since 2.0.0
  279. */
  280. export function leftOrBoth(e) {
  281. return function (ma) { return (_.isNone(ma) ? left(e) : both(e, ma.value)); };
  282. }
  283. // TODO: make lazy in v3
  284. /**
  285. * @example
  286. * import { rightOrBoth, right, both } from 'fp-ts/These'
  287. * import { none, some } from 'fp-ts/Option'
  288. *
  289. * assert.deepStrictEqual(rightOrBoth(1)(none), right(1))
  290. * assert.deepStrictEqual(rightOrBoth(1)(some('a')), both('a', 1))
  291. *
  292. * @category constructors
  293. * @since 2.0.0
  294. */
  295. export function rightOrBoth(a) {
  296. return function (me) { return (_.isNone(me) ? right(a) : both(me.value, a)); };
  297. }
  298. /**
  299. * Returns the `E` value if and only if the value is constructed with `Left`
  300. *
  301. * @example
  302. * import { getLeftOnly, left, right, both } from 'fp-ts/These'
  303. * import { none, some } from 'fp-ts/Option'
  304. *
  305. * assert.deepStrictEqual(getLeftOnly(left('a')), some('a'))
  306. * assert.deepStrictEqual(getLeftOnly(right(1)), none)
  307. * assert.deepStrictEqual(getLeftOnly(both('a', 1)), none)
  308. *
  309. * @category conversions
  310. * @since 2.0.0
  311. */
  312. export function getLeftOnly(fa) {
  313. return isLeft(fa) ? _.some(fa.left) : _.none;
  314. }
  315. /**
  316. * Returns the `A` value if and only if the value is constructed with `Right`
  317. *
  318. * @example
  319. * import { getRightOnly, left, right, both } from 'fp-ts/These'
  320. * import { none, some } from 'fp-ts/Option'
  321. *
  322. * assert.deepStrictEqual(getRightOnly(left('a')), none)
  323. * assert.deepStrictEqual(getRightOnly(right(1)), some(1))
  324. * assert.deepStrictEqual(getRightOnly(both('a', 1)), none)
  325. *
  326. * @category conversions
  327. * @since 2.0.0
  328. */
  329. export function getRightOnly(fa) {
  330. return isRight(fa) ? _.some(fa.right) : _.none;
  331. }
  332. /**
  333. * Takes a pair of `Option`s and attempts to create a `These` from them
  334. *
  335. * @example
  336. * import { fromOptions, left, right, both } from 'fp-ts/These'
  337. * import { none, some } from 'fp-ts/Option'
  338. *
  339. * assert.deepStrictEqual(fromOptions(none, none), none)
  340. * assert.deepStrictEqual(fromOptions(some('a'), none), some(left('a')))
  341. * assert.deepStrictEqual(fromOptions(none, some(1)), some(right(1)))
  342. * assert.deepStrictEqual(fromOptions(some('a'), some(1)), some(both('a', 1)))
  343. *
  344. * @category conversions
  345. * @since 2.0.0
  346. */
  347. export var fromOptions = function (fe, fa) {
  348. return _.isNone(fe)
  349. ? _.isNone(fa)
  350. ? _.none
  351. : _.some(right(fa.value))
  352. : _.isNone(fa)
  353. ? _.some(left(fe.value))
  354. : _.some(both(fe.value, fa.value));
  355. };
  356. var _map = function (fa, f) { return pipe(fa, map(f)); };
  357. /* istanbul ignore next */
  358. var _bimap = function (fa, f, g) { return pipe(fa, bimap(f, g)); };
  359. /* istanbul ignore next */
  360. var _mapLeft = function (fa, f) { return pipe(fa, mapLeft(f)); };
  361. /* istanbul ignore next */
  362. var _reduce = function (fa, b, f) { return pipe(fa, reduce(b, f)); };
  363. /* istanbul ignore next */
  364. var _foldMap = function (M) {
  365. var foldMapM = foldMap(M);
  366. return function (fa, f) { return pipe(fa, foldMapM(f)); };
  367. };
  368. /* istanbul ignore next */
  369. var _reduceRight = function (fa, b, f) { return pipe(fa, reduceRight(b, f)); };
  370. /* istanbul ignore next */
  371. var _traverse = function (F) {
  372. var traverseF = traverse(F);
  373. return function (ta, f) { return pipe(ta, traverseF(f)); };
  374. };
  375. /**
  376. * Map a pair of functions over the two type arguments of the bifunctor.
  377. *
  378. * @category mapping
  379. * @since 2.0.0
  380. */
  381. export var bimap = function (f, g) { return function (fa) {
  382. return isLeft(fa) ? left(f(fa.left)) : isRight(fa) ? right(g(fa.right)) : both(f(fa.left), g(fa.right));
  383. }; };
  384. /**
  385. * Map a function over the first type argument of a bifunctor.
  386. *
  387. * @category error handling
  388. * @since 2.0.0
  389. */
  390. export var mapLeft = function (f) { return function (fa) {
  391. return isLeft(fa) ? left(f(fa.left)) : isBoth(fa) ? both(f(fa.left), fa.right) : fa;
  392. }; };
  393. /**
  394. * `map` can be used to turn functions `(a: A) => B` into functions `(fa: F<A>) => F<B>` whose argument and return types
  395. * use the type constructor `F` to represent some computational context.
  396. *
  397. * @category mapping
  398. * @since 2.0.0
  399. */
  400. export var map = function (f) { return function (fa) {
  401. return isLeft(fa) ? fa : isRight(fa) ? right(f(fa.right)) : both(fa.left, f(fa.right));
  402. }; };
  403. /**
  404. * @category folding
  405. * @since 2.0.0
  406. */
  407. export var reduce = function (b, f) { return function (fa) {
  408. return isLeft(fa) ? b : f(b, fa.right);
  409. }; };
  410. /**
  411. * @category folding
  412. * @since 2.0.0
  413. */
  414. export var foldMap = function (M) { return function (f) { return function (fa) {
  415. return isLeft(fa) ? M.empty : f(fa.right);
  416. }; }; };
  417. /**
  418. * @category folding
  419. * @since 2.0.0
  420. */
  421. export var reduceRight = function (b, f) { return function (fa) {
  422. return isLeft(fa) ? b : f(fa.right, b);
  423. }; };
  424. /**
  425. * @category traversing
  426. * @since 2.6.3
  427. */
  428. export var traverse = function (F) {
  429. return function (f) {
  430. return function (ta) {
  431. return isLeft(ta) ? F.of(ta) : isRight(ta) ? F.map(f(ta.right), right) : F.map(f(ta.right), function (b) { return both(ta.left, b); });
  432. };
  433. };
  434. };
  435. /**
  436. * @category traversing
  437. * @since 2.6.3
  438. */
  439. export var sequence = function (F) {
  440. return function (ta) {
  441. return isLeft(ta) ? F.of(ta) : isRight(ta) ? F.map(ta.right, right) : F.map(ta.right, function (b) { return both(ta.left, b); });
  442. };
  443. };
  444. /**
  445. * @category constructors
  446. * @since 2.0.0
  447. */
  448. export var of = right;
  449. /**
  450. * @category type lambdas
  451. * @since 2.0.0
  452. */
  453. export var URI = 'These';
  454. /**
  455. * @category instances
  456. * @since 2.7.0
  457. */
  458. export var Functor = {
  459. URI: URI,
  460. map: _map
  461. };
  462. /**
  463. * @category mapping
  464. * @since 2.10.0
  465. */
  466. export var flap = /*#__PURE__*/ flap_(Functor);
  467. /**
  468. * @category instances
  469. * @since 2.10.0
  470. */
  471. export var Pointed = {
  472. URI: URI,
  473. of: of
  474. };
  475. /**
  476. * @category instances
  477. * @since 2.7.0
  478. */
  479. export var Bifunctor = {
  480. URI: URI,
  481. bimap: _bimap,
  482. mapLeft: _mapLeft
  483. };
  484. /**
  485. * @category instances
  486. * @since 2.11.0
  487. */
  488. export var FromThese = {
  489. URI: URI,
  490. fromThese: identity
  491. };
  492. /**
  493. * @category instances
  494. * @since 2.7.0
  495. */
  496. export var Foldable = {
  497. URI: URI,
  498. reduce: _reduce,
  499. foldMap: _foldMap,
  500. reduceRight: _reduceRight
  501. };
  502. /**
  503. * @category instances
  504. * @since 2.7.0
  505. */
  506. export var Traversable = {
  507. URI: URI,
  508. map: _map,
  509. reduce: _reduce,
  510. foldMap: _foldMap,
  511. reduceRight: _reduceRight,
  512. traverse: _traverse,
  513. sequence: sequence
  514. };
  515. /**
  516. * @category instances
  517. * @since 2.10.0
  518. */
  519. export var FromEither = {
  520. URI: URI,
  521. fromEither: identity
  522. };
  523. /**
  524. * @category lifting
  525. * @since 2.13.0
  526. */
  527. export var fromPredicate = /*#__PURE__*/ fromPredicate_(FromEither);
  528. /**
  529. * @category conversions
  530. * @since 2.10.0
  531. */
  532. export var fromOption =
  533. /*#__PURE__*/ fromOption_(FromEither);
  534. /**
  535. * @category lifting
  536. * @since 2.10.0
  537. */
  538. export var fromOptionK =
  539. /*#__PURE__*/ fromOptionK_(FromEither);
  540. // -------------------------------------------------------------------------------------
  541. // utils
  542. // -------------------------------------------------------------------------------------
  543. /**
  544. * @since 2.11.0
  545. */
  546. export var elem = function (E) {
  547. return function (a) {
  548. return function (ma) {
  549. return isLeft(ma) ? false : E.equals(a, ma.right);
  550. };
  551. };
  552. };
  553. /**
  554. * @since 2.11.0
  555. */
  556. export var exists = function (predicate) {
  557. return function (ma) {
  558. return isLeft(ma) ? false : predicate(ma.right);
  559. };
  560. };
  561. /**
  562. * @example
  563. * import { toTuple2, left, right, both } from 'fp-ts/These'
  564. *
  565. * assert.deepStrictEqual(toTuple2(() => 'a', () => 1)(left('b')), ['b', 1])
  566. * assert.deepStrictEqual(toTuple2(() => 'a', () => 1)(right(2)), ['a', 2])
  567. * assert.deepStrictEqual(toTuple2(() => 'a', () => 1)(both('b', 2)), ['b', 2])
  568. *
  569. * @category conversions
  570. * @since 2.10.0
  571. */
  572. export var toTuple2 = function (e, a) {
  573. return function (fa) {
  574. return isLeft(fa) ? [fa.left, a()] : isRight(fa) ? [e(), fa.right] : [fa.left, fa.right];
  575. };
  576. };
  577. // -------------------------------------------------------------------------------------
  578. // deprecated
  579. // -------------------------------------------------------------------------------------
  580. /**
  581. * Use [`toTuple2`](#totuple2) instead.
  582. *
  583. * @category zone of death
  584. * @since 2.0.0
  585. * @deprecated
  586. */
  587. export var toTuple = function (e, a) {
  588. return toTuple2(function () { return e; }, function () { return a; });
  589. };
  590. /**
  591. * @since 2.11.0
  592. */
  593. export var ApT = /*#__PURE__*/ of(_.emptyReadonlyArray);
  594. // -------------------------------------------------------------------------------------
  595. // array utils
  596. // -------------------------------------------------------------------------------------
  597. /**
  598. * Equivalent to `ReadonlyNonEmptyArray#traverseWithIndex(getApplicative(S))`.
  599. *
  600. * @category traversing
  601. * @since 2.11.0
  602. */
  603. export var traverseReadonlyNonEmptyArrayWithIndex = function (S) {
  604. return function (f) {
  605. return function (as) {
  606. var e = _.none;
  607. var t = f(0, _.head(as));
  608. if (isLeft(t)) {
  609. return t;
  610. }
  611. if (isBoth(t)) {
  612. e = _.some(t.left);
  613. }
  614. var out = [t.right];
  615. for (var i = 1; i < as.length; i++) {
  616. var t_1 = f(i, as[i]);
  617. if (isLeft(t_1)) {
  618. return t_1;
  619. }
  620. if (isBoth(t_1)) {
  621. e = _.isNone(e) ? _.some(t_1.left) : _.some(S.concat(e.value, t_1.left));
  622. }
  623. out.push(t_1.right);
  624. }
  625. return _.isNone(e) ? right(out) : both(e.value, out);
  626. };
  627. };
  628. };
  629. /**
  630. * Equivalent to `ReadonlyArray#traverseWithIndex(getApplicative(S))`.
  631. *
  632. * @category traversing
  633. * @since 2.11.0
  634. */
  635. export var traverseReadonlyArrayWithIndex = function (S) {
  636. return function (f) {
  637. var g = traverseReadonlyNonEmptyArrayWithIndex(S)(f);
  638. return function (as) { return (_.isNonEmpty(as) ? g(as) : ApT); };
  639. };
  640. };
  641. // -------------------------------------------------------------------------------------
  642. // deprecated
  643. // -------------------------------------------------------------------------------------
  644. /**
  645. * This instance is deprecated, use small, specific instances instead.
  646. * For example if a function needs a `Functor` instance, pass `T.Functor` instead of `T.these`
  647. * (where `T` is from `import T from 'fp-ts/These'`)
  648. *
  649. * @category zone of death
  650. * @since 2.0.0
  651. * @deprecated
  652. */
  653. export var these = {
  654. URI: URI,
  655. map: _map,
  656. bimap: _bimap,
  657. mapLeft: _mapLeft,
  658. reduce: _reduce,
  659. foldMap: _foldMap,
  660. reduceRight: _reduceRight,
  661. traverse: _traverse,
  662. sequence: sequence
  663. };