From 38343d7ec038093fde69199d966f5aed8f65412d Mon Sep 17 00:00:00 2001 From: rowan Date: Wed, 9 Apr 2025 23:17:38 -0500 Subject: [PATCH] split monad law tests, add setoid to Option and Result --- src/algebra/option.js | 6 ++--- src/algebra/result.js | 6 ++--- tests/units/monad.js | 58 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/algebra/option.js b/src/algebra/option.js index 394e63c..945431d 100644 --- a/src/algebra/option.js +++ b/src/algebra/option.js @@ -1,9 +1,9 @@ -import { Algebra, Foldable, Monad, Monoid } from './interfaces.js' +import { Algebra, Foldable, Monad, Monoid, Setoid } from './interfaces.js' /** @import { Morphism } from './types.js' */ /** @template T */ -export class Some extends Algebra(Monoid, Monad, Foldable) { +export class Some extends Algebra(Setoid, Monoid, Monad, Foldable) { /** @type {T} */ #value @@ -71,7 +71,7 @@ export class Some extends Algebra(Monoid, Monad, Foldable) { } /** @template T */ -export class None extends Algebra(Monoid, Monad, Foldable) { +export class None extends Algebra(Setoid, Monoid, Monad, Foldable) { equals(other) { return other === none } diff --git a/src/algebra/result.js b/src/algebra/result.js index f31e1b5..16ce285 100644 --- a/src/algebra/result.js +++ b/src/algebra/result.js @@ -1,11 +1,11 @@ -import { Algebra, Foldable, Functor, Monad } from './interfaces.js' +import { Algebra, Foldable, Functor, Monad, Setoid } from './interfaces.js' /** @import { Morphism } from './types.js' */ /** * @template T, E */ -export class Ok extends Algebra(Monad, Foldable) { +export class Ok extends Algebra(Setoid, Monad, Foldable) { /** @type {T} */ #value @@ -83,7 +83,7 @@ export class Ok extends Algebra(Monad, Foldable) { /** * @template T, E */ -export class Err extends Algebra(Functor, Monad) { +export class Err extends Algebra(Setoid, Functor, Monad) { /** @type {E} */ #value diff --git a/tests/units/monad.js b/tests/units/monad.js index d54178b..e052733 100644 --- a/tests/units/monad.js +++ b/tests/units/monad.js @@ -1,6 +1,8 @@ import { it, assert } from 'folktest' import { Option, Result } from '../../src/index.js' +const Monads = [Option, Result] + const leftIdentity = (M, a, f) => { assert(M(a).chain(f).equals(f(a))) } @@ -19,17 +21,53 @@ export const prove = (M, m, a, f, g) => { associativity(m, f, g) } -export const Tests = [ - it('should adhere to monadic laws', () => { - [Option, Result].forEach(F => { - const Ctr = F.of +const inc = F => x => F.of(x + 1) +const dbl = F => x => F.of(x * 2) - prove( - Ctr, - Ctr(1), - 1, - x => Ctr(x + 1), - x => Ctr(x * 2) +export const Tests = [ + it('unit is a left identity', () => { + Monads.forEach(monad => { + const f = inc(monad) + // NOTE: okay but like, shut up + // @ts-ignore + assert(monad.of(1).chain(f).equals(f(1))) + }) + //prove( + // Ctr, M + // Ctr(1), m + // 1, a + // x => Ctr(x + 1), f + // x => Ctr(x * 2) g + //) + }), + + it('unit is a right identity', () => { + Monads.forEach(monad => { + const m = monad.of(1) + + assert( + // NOTE: i heard this one already + // @ts-ignore + m.chain(monad.of).equals(m) + ) + }) + }), + + it('unit is associative', () => { + Monads.forEach(monad => { + const m = monad.of(1) + const f = inc(monad) + const g = dbl(monad) + console.log(m.chain(f)) + + // NOTE: it was better the first time + // @ts-ignore + const x = m.chain(f).chain(g) + // @ts-ignore + const y = m.chain(x => f(x).chain(g)) + + assert( + x.equals(y) ) }) })