All files / src/laws/typeclass/parameterized Monad.ts

100% Statements 33/33
100% Branches 4/4
100% Functions 1/1
100% Lines 33/33

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 591x   1x   1x 1x   1x           1x 10x 10x 10x 10x   10x 10x 10x 10x 10x 10x 10x 10x   10x 10x 10x 10x 10x   10x 10x 10x 10x 10x 10x 901x 10x 10x 10x                              
import {Law, LawSet} from '#law'
import {Monad as MD} from '@effect/typeclass'
import {flow, pipe} from 'effect'
import type {TypeLambda} from 'effect/HKT'
import {covariantLaws} from './Covariant.js'
import {flatMapLaws} from './FlatMap.js'
import type {BuildParameterized} from './given.js'
import {unfoldGiven} from './given.js'
 
/**
 * Typeclass laws for `Monad`.
 * @category typeclass laws
 */
export const monadLaws: BuildParameterized<MonadTypeLambda> = (
  given,
  suffix?,
) => {
  const {a, F, fa, equalsFa, equalsFb, ab, afb} = unfoldGiven(given)
 
  return LawSet(covariantLaws(given), flatMapLaws(given))(
    `Monad${suffix ?? ''}`,
    Law(
      'left identity',
      'of ∘ flatMap(afb) = afb',
      a,
      afb,
    )((a, afb) => equalsFb(pipe(a, F.of, F.flatMap(afb)), afb(a))),
 
    Law(
      'right identity',
      'flatMap(of) = id',
      fa,
    )(fa => equalsFa(pipe(fa, F.flatMap(F.of)), fa)),
 
    Law(
      'map consistency',
      'map(ab) = flatMap(of ∘ ab)',
      fa,
      ab,
    )((fa, ab) =>
      equalsFb(pipe(fa, F.map(ab)), pipe(fa, F.flatMap(flow(ab, F.of)))),
    ),
  )
}
 
/**
 * Type lambda for the `Monad` typeclass.
 * @category type lambda
 */
export interface MonadTypeLambda extends TypeLambda {
  readonly type: MD.Monad<this['Target'] & TypeLambda>
}
 
declare module './given.js' {
  interface ParameterizedLambdas {
    Monad: MonadTypeLambda
  }
}