diff --git a/src/algebra/option.js b/src/algebra/option.js index 8de9f80..394e63c 100644 --- a/src/algebra/option.js +++ b/src/algebra/option.js @@ -23,6 +23,11 @@ export class Some extends Algebra(Monoid, Monad, Foldable) { return new Some(value) } + equals(other) { + return other instanceof Some && + other.chain(v => v === this.#value) + } + /** * @template R * @param {Morphism} f @@ -67,6 +72,10 @@ export class Some extends Algebra(Monoid, Monad, Foldable) { /** @template T */ export class None extends Algebra(Monoid, Monad, Foldable) { + equals(other) { + return other === none + } + /** * @template R * @param {Morphism} _f diff --git a/src/algebra/result.js b/src/algebra/result.js index f7a18f6..f31e1b5 100644 --- a/src/algebra/result.js +++ b/src/algebra/result.js @@ -19,6 +19,11 @@ export class Ok extends Algebra(Monad, Foldable) { this.#value = value } + equals(other) { + return other instanceof Ok && + other.chain(v => v === this.#value) + } + /** @returns {this is Ok} */ isOk() { return true } @@ -92,6 +97,11 @@ export class Err extends Algebra(Functor, Monad) { this.#value = value } + equals(other) { + return other instanceof Err && + other.chain(v => v === this.#value) + } + /** @returns {this is Ok} */ isOk() { return false } diff --git a/tests/units/monad.js b/tests/units/monad.js index cfdf2b2..d54178b 100644 --- a/tests/units/monad.js +++ b/tests/units/monad.js @@ -1,16 +1,16 @@ -import { it, assertEq } from 'folktest' -import { Ok, Err, Some, None } from '../../src/index.js' +import { it, assert } from 'folktest' +import { Option, Result } from '../../src/index.js' const leftIdentity = (M, a, f) => { - assertEq(M(a).bind(f), f(a)) + assert(M(a).chain(f).equals(f(a))) } const rightIdentity = (M, m) => { - assertEq(m.bind(M), m) + assert(m.chain(M).equals(m)) } const associativity = (m, f, g) => { - assertEq(m.bind(f).bind(g), m.bind(x => f(x).bind(g))) + assert(m.chain(f).chain(g).equals(m.chain(x => f(x).chain(g)))) } export const prove = (M, m, a, f, g) => { @@ -21,13 +21,15 @@ export const prove = (M, m, a, f, g) => { export const Tests = [ it('should adhere to monadic laws', () => { - [Ok, Err, Some, None].forEach(ctr => { + [Option, Result].forEach(F => { + const Ctr = F.of + prove( - ctr, - ctr(1), + Ctr, + Ctr(1), 1, - x => ctr(x + 1), - x => ctr(x * 2) + x => Ctr(x + 1), + x => Ctr(x * 2) ) }) })