diff --git a/CHANGELOG.md b/CHANGELOG.md index f93cb10..457c593 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] :bomb: +## :bulb: [0.5.1] - 2020-03-23 + +### :hammer: Fixed +- `Either.chain` was fixed. The behaviour will be correct. + ## :bulb: [0.5.0] - 2020-03-20 ### :gift: Added @@ -65,7 +70,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Smoke test and really build to **Travis CI**. - Labels of `npm`, `coverage`, `travis`. -[unreleased]: https://github.com/snatvb/monad-maniac/compare/v0.5.0...develop +[unreleased]: https://github.com/snatvb/monad-maniac/compare/v0.5.1...develop +[0.5.1]: https://github.com/snatvb/monad-maniac/compare/v0.5.0...v0.5.1 [0.5.0]: https://github.com/snatvb/monad-maniac/compare/v0.4.0...v0.5.0 [0.4.0]: https://github.com/snatvb/monad-maniac/compare/v0.3.0...v0.4.0 [0.3.0]: https://github.com/snatvb/monad-maniac/compare/v0.2.0...v0.3.0 diff --git a/src/either.ts b/src/either.ts index f7807b6..21b8640 100644 --- a/src/either.ts +++ b/src/either.ts @@ -1,7 +1,7 @@ import * as helpers from './helpers' +import { Functor } from './interfaces' import * as Maybe from './maybe' import { Nullable } from './types' -import { Functor } from './interfaces' /** Mather type for caseOf */ export type CaseOf = { @@ -83,7 +83,7 @@ export interface Either extends Functor { * ``` * @param f Function to apply for Right value */ - chain(f: (value: R) => U): U | Either + chain(f: (value: R) => Either): Either /** * Apply predicate function to value in container. * If the function returns not `true` then value from @@ -433,15 +433,17 @@ export function map(f: (value: R) => U, either?: Either): Either< * const result: Either.Shape = typeof name === 'string' * ? new Either.Right(name) * : new Either.Left('Server error') - * const greeting = Either.chain((name) => `Welcome, ${name}!`, result) // 'Welcome, Jake' or 'Server error' + * const greeting = Either.chain( + * (name: string) => Either.right(`Welcome, ${name}!`) + * ), result).get() // 'Welcome, Jake' or 'Server error' * ``` * */ -export function chain(f: (value: R) => U, either: Either): Either | U +export function chain(f: (value: R) => Either, either: Either): Either /** * Just curried `chain`. */ -export function chain(f: (value: R) => U): (either: Either) => Either | U -export function chain(f: (value: R) => U, either?: Either): Either | U | ((either: Either) => Either | U) { +export function chain(f: (value: R) => Either): (either: Either) => Either +export function chain(f: (value: R) => Either, either?: Either): Either | ((either: Either) => Either) { const op = (either: Either) => either.chain(f) return helpers.curry1(op, either) } @@ -580,7 +582,7 @@ export class Right implements Either { return this.value } - chain(f: (value: R) => U): U | Either { + chain(f: (value: R) => Either): Either { return f(this.value) } @@ -628,7 +630,7 @@ export class Left implements Either { return f(this.value) } - chain(_f: (value: R) => U): U | Either { + chain(_f: (value: R) => Either): Either { return new Left(this.value) } diff --git a/tests/either.test.ts b/tests/either.test.ts index 7ceaab4..72ee989 100644 --- a/tests/either.test.ts +++ b/tests/either.test.ts @@ -1,6 +1,8 @@ import { Either } from '../src' const double = (x: number): number => x * 2 +const chainDouble = (x: number): Either.Shape => Either.right(x * 2) +const greetChain = (name: string): Either.Shape => Either.right(`Welcome, ${name}!`) describe('Either pure functions', () => { describe('of', () => { @@ -84,19 +86,19 @@ describe('Either pure functions', () => { it('direct call', () => { const left: Either.Shape = new Either.Left('Server error') const right: Either.Shape = new Either.Right(150) - const leftResult = Either.chain(double, left) + const leftResult = Either.chain(chainDouble, left) expect(leftResult instanceof Either.Left).toBe(true) - expect(Either.chain(double, right)).toBe(300) + expect(Either.chain(chainDouble, right).get()).toBe(300) }) it('carried', () => { const left: Either.Shape = new Either.Left('Server error') const right: Either.Shape = new Either.Right(150) - const leftResult = Either.chain(double)(left) + const leftResult = Either.chain(chainDouble)(left) expect(leftResult instanceof Either.Left).toBe(true) - expect(Either.chain(double)(right)).toBe(300) + expect(Either.chain(chainDouble)(right).get()).toBe(300) }) }) @@ -280,8 +282,8 @@ describe('Either: Left & Right', () => { const left: Either.Shape = new Either.Left('Server error') const right: Either.Shape = new Either.Right(150) - expect(left.chain(double) instanceof Either.Left).toBe(true) - expect(right.chain(double)).toBe(300) + expect(left.chain(chainDouble).isLeft()).toBe(true) + expect(right.chain(chainDouble).isRight()).toBe(true) }) it('getOrElse', () => { @@ -344,10 +346,10 @@ describe('Either: Left & Right', () => { describe('Cases from docs', () => { it('map', () => { const divide = (dividend: number) => (divider: number): Either.Shape => { - if (divider === 0) { - return Either.left('Divider is zero!') - } - return Either.right(dividend / divider) + if (divider === 0) { + return Either.left('Divider is zero!') + } + return Either.right(dividend / divider) } const resultNormal = divide(10)(5).map(double).get() // 4 @@ -358,10 +360,10 @@ describe('Cases from docs', () => { it('chain', () => { const divide = (dividend: number) => (divider: number): Either.Shape => { - if (divider === 0) { - return Either.left('Divider is zero!') - } - return Either.right(dividend / divider) + if (divider === 0) { + return Either.left('Divider is zero!') + } + return Either.right(dividend / divider) } const nonZeroMultiply = (multiplicand: number) => (factor: number): Either.Shape => { @@ -471,4 +473,16 @@ describe('Cases from docs', () => { expect(resultRight.toString()).toBe('Just(150)') expect(resultRightVoid.toString()).toBe('Nothing()') }) + + // ========= DOC TESTS ========= + it('Chain from doc', () => { + + const greeting = Either.chain(greetChain, Either.right('Jake')).get() + expect(greeting).toBe('Welcome, Jake!') + + // Server error + + const serverError = Either.chain(greetChain, Either.left('Server error')).get() + expect(serverError).toBe('Server error') + }) })