Skip to content
This repository has been archived by the owner on Jan 9, 2024. It is now read-only.

Commit

Permalink
Added cata for Maybe and Either (#36)
Browse files Browse the repository at this point in the history
* Added cata for Maybe

* Added docs in Maybe for cata

* Added  for Either
  • Loading branch information
snatvb committed Mar 11, 2021
1 parent 37c5efa commit a11da00
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 0 deletions.
14 changes: 14 additions & 0 deletions src/either.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ export interface Either<L, R> extends Functor<R> {
* ```
*/
caseOf<U>(matcher: CaseOf<L, R, U>): 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<U>(leftFn: (value: L) => U, rightFn: (value: R) => U): U
/**
* Converting `Either` to `Maybe`.
* If value in `Left` will returns `Nothing`, else
Expand Down Expand Up @@ -697,6 +705,9 @@ export class Right<L, R> implements Either<L, R> {
caseOf<U>(matcher: CaseOf<L, R, U>): U {
return matcher.Right(this.value)
}
cata<U>(_: (value: L) => U, rightFn: (value: R) => U): U {
return rightFn(this.value)
}
toMaybe(): Maybe.Shape<R> {
return Maybe.of(this.value)
}
Expand Down Expand Up @@ -746,6 +757,9 @@ export class Left<L, R> implements Either<L, R> {
caseOf<U>(matcher: CaseOf<L, R, U>): U {
return matcher.Left(this.value)
}
cata<U>(leftFn: (value: L) => U): U {
return leftFn(this.value)
}
toMaybe(): Maybe.Shape<R> {
return Maybe.nothing()
}
Expand Down
16 changes: 16 additions & 0 deletions src/maybe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,14 @@ export interface Maybe<T> extends Functor<T>, Applicative<T> {
*/
caseOf<U>(matcher: CaseOf<T, U>): 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<U>(justFn: (value: NonNullable<T>) => U, nothingFn: () => U): U

/**
* Unwrap `Maybe` from `Maybe`, if in `Maybe` will not `Maybe` then returns `Nothing`.
*
Expand Down Expand Up @@ -672,6 +680,10 @@ export class Just<T> implements Maybe<T> {
return matcher.Just(this.value)
}

cata<U>(justFn: (value: NonNullable<T>) => U): U {
return justFn(this.value)
}

/** Method implements from [`Maybe.join`](../interfaces/_maybe_.maybe.html#join) */
join(): JoinMaybe<T> {
return (this.value instanceof Just
Expand Down Expand Up @@ -749,6 +761,10 @@ export class Nothing<T> implements Maybe<T> {
return matcher.Nothing()
}

cata<U>(_: (value: NonNullable<T>) => U, nothingFn: () => U): U {
return nothingFn()
}

/** Method implements from [`Maybe.join`](../interfaces/_maybe_.maybe.html#join) */
join(): JoinMaybe<T> {
return new Nothing() as JoinMaybe<T>
Expand Down
9 changes: 9 additions & 0 deletions tests/either.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Either } from '../src'

const double = (x: number): number => x * 2
const identity = <T>(x: T) => x
const chainDouble = (x: number): Either.Shape<string, number> =>
Either.right(x * 2)
const greetChain = (name: string): Either.Shape<string, string> =>
Expand Down Expand Up @@ -374,6 +375,14 @@ describe('Either: Left & Right', () => {
expect(right.caseOf(matcher)).toBe(300)
})

it('cata', () => {
const left: Either.Shape<string, number> = new Either.Left('Server error')
const right: Either.Shape<string, number> = 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<number, number> = new Either.Left(150)
Expand Down
22 changes: 22 additions & 0 deletions tests/maybe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit a11da00

Please sign in to comment.