split monad law tests, add setoid to Option and Result

This commit is contained in:
Rowan 2025-04-09 23:17:38 -05:00
parent 48a3670172
commit 38343d7ec0
3 changed files with 54 additions and 16 deletions

View file

@ -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
}

View file

@ -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

View file

@ -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)
)
})
})