From a11da0095331bf54952f245d804254f5032eef95 Mon Sep 17 00:00:00 2001 From: Andrew Brigthon Date: Fri, 12 Mar 2021 00:26:09 +0300 Subject: [PATCH 1/2] Added cata for Maybe and Either (#36) * Added cata for Maybe * Added docs in Maybe for cata * Added for Either --- src/either.ts | 14 ++++++++++++++ src/maybe.ts | 16 ++++++++++++++++ tests/either.test.ts | 9 +++++++++ tests/maybe.test.ts | 22 ++++++++++++++++++++++ 4 files changed, 61 insertions(+) diff --git a/src/either.ts b/src/either.ts index d00d2b1..53a828d 100644 --- a/src/either.ts +++ b/src/either.ts @@ -209,6 +209,14 @@ export interface Either extends Functor { * ``` */ caseOf(matcher: CaseOf): U + + /** + * Works like caseOf, but use two functions as arguments for unwrap + * instead of object allocation. + * @param leftFn Function will called with Left + * @param rightFn Function will called with Right + */ + cata(leftFn: (value: L) => U, rightFn: (value: R) => U): U /** * Converting `Either` to `Maybe`. * If value in `Left` will returns `Nothing`, else @@ -697,6 +705,9 @@ export class Right implements Either { caseOf(matcher: CaseOf): U { return matcher.Right(this.value) } + cata(_: (value: L) => U, rightFn: (value: R) => U): U { + return rightFn(this.value) + } toMaybe(): Maybe.Shape { return Maybe.of(this.value) } @@ -746,6 +757,9 @@ export class Left implements Either { caseOf(matcher: CaseOf): U { return matcher.Left(this.value) } + cata(leftFn: (value: L) => U): U { + return leftFn(this.value) + } toMaybe(): Maybe.Shape { return Maybe.nothing() } diff --git a/src/maybe.ts b/src/maybe.ts index fd36765..a9bd82e 100644 --- a/src/maybe.ts +++ b/src/maybe.ts @@ -179,6 +179,14 @@ export interface Maybe extends Functor, Applicative { */ caseOf(matcher: CaseOf): U + /** + * Works like caseOf, but use two functions as arguments for unwrap + * instead of object allocation. + * @param justFn Function will called with Just + * @param nothingFn Function will called with Nothing + */ + cata(justFn: (value: NonNullable) => U, nothingFn: () => U): U + /** * Unwrap `Maybe` from `Maybe`, if in `Maybe` will not `Maybe` then returns `Nothing`. * @@ -672,6 +680,10 @@ export class Just implements Maybe { return matcher.Just(this.value) } + cata(justFn: (value: NonNullable) => U): U { + return justFn(this.value) + } + /** Method implements from [`Maybe.join`](../interfaces/_maybe_.maybe.html#join) */ join(): JoinMaybe { return (this.value instanceof Just @@ -749,6 +761,10 @@ export class Nothing implements Maybe { return matcher.Nothing() } + cata(_: (value: NonNullable) => U, nothingFn: () => U): U { + return nothingFn() + } + /** Method implements from [`Maybe.join`](../interfaces/_maybe_.maybe.html#join) */ join(): JoinMaybe { return new Nothing() as JoinMaybe diff --git a/tests/either.test.ts b/tests/either.test.ts index 8362b93..73d6d0f 100644 --- a/tests/either.test.ts +++ b/tests/either.test.ts @@ -1,6 +1,7 @@ import { Either } from '../src' const double = (x: number): number => x * 2 +const identity = (x: T) => x const chainDouble = (x: number): Either.Shape => Either.right(x * 2) const greetChain = (name: string): Either.Shape => @@ -374,6 +375,14 @@ describe('Either: Left & Right', () => { expect(right.caseOf(matcher)).toBe(300) }) + it('cata', () => { + const left: Either.Shape = new Either.Left('Server error') + const right: Either.Shape = new Either.Right(150) + + expect(left.cata((msg) => msg.length, identity)).toBe(12) + expect(right.cata(() => 10, double)).toBe(300) + }) + it('filter', () => { const predicate = (x: number) => x > 150 const left: Either.Shape = new Either.Left(150) diff --git a/tests/maybe.test.ts b/tests/maybe.test.ts index 6ad6faa..c264add 100644 --- a/tests/maybe.test.ts +++ b/tests/maybe.test.ts @@ -457,6 +457,28 @@ describe('Just and Nothing', () => { ).toBe(0) }) + it('cata', () => { + const just = Maybe.of(5) + expect(just.toString()).toBe('Just(5)') + expect( + just.map(double).cata( + (x) => x + 5, + () => 0, + ), + ).toBe(15) + expect( + just + .map(double) + .map(double) + .map(toNothing) + .map(double) + .cata( + (x) => x + 5, + () => 0, + ), + ).toBe(0) + }) + it('join', () => { const just = Maybe.of(5) const nestedJust = Maybe.of(just) From 6ecd64d533e1936d2f802f923528e39f22af2cdb Mon Sep 17 00:00:00 2001 From: Andrew Brighton Date: Fri, 12 Mar 2021 00:32:05 +0300 Subject: [PATCH 2/2] Bump version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7a0a5b1..c306e9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monad-maniac", - "version": "0.6.0", + "version": "0.6.1", "description": "monads with right rules", "scripts": { "ts:cjs": "yarn tsc -p ts/cjs.tsconfig.json",