nim_iterator_stream_experiment/monad/monadlaws

Utilities to check whether a type M obeys the monad laws.

This module is meant to be used in test suites. It should not be imported with lazymonadlaws.

M must have:
  • A flatMap[A; B] procedure with the signature (M[A], A -> M[B]) -> M[B].
  • An equality operator.

Concepts cannot currently be used to implement the monad concept in Nim. See this related issue .

Examples:

Types

LeftIdentitySpec[A; MA; MB] = tuple[initial: A, lift: A -> MA, f: A -> MB]
Parameters for the left identity law.   Source Edit
RightIdentitySpec[T; M] = tuple[expected: T, lift: T -> M]
Parameters for the right identity law.   Source Edit
AssociativitySpec[A; B; MA; MB; MC] = tuple[initial: A, lift: A -> MA, f: A -> MB, g: B -> MC]
Parameters for the associativity law.   Source Edit
MonadLawsSpec[LA; LMA; LMB; RT; RM; AA; AB; AMA; AMB; AMC] = tuple[
    leftIdentity: LeftIdentitySpec[LA, LMA, LMB],
    rightIdentity: RightIdentitySpec[RT, RM],
    associativity: AssociativitySpec[AA, AB, AMA, AMB, AMC]]
  Source Edit

Funcs

func leftIdentitySpec[A; MA; MB](initial: A; lift: A -> MA; f: A -> MB): LeftIdentitySpec[A,
    MA, MB]
  • lift: A procedure to lift a value to a monad.
  • f: The procedure passed to flatMap defined by the tested monad type.
  • runArg: The argument passed to run as defined in LazyMonad.
  Source Edit
func rightIdentitySpec[T; M](expected: T; lift: T -> M): RightIdentitySpec[T, M]
  • expected: The starting value on the left side of the equation, the final value on the right side.
  • lift: A procedure to lift a value to a monad.
  • runArg: The argument passed to run as defined in LazyMonad.
  Source Edit
func associativitySpec[A; B; MA; MB; MC](initial: A; lift: A -> MA; f: A -> MB; g: B -> MC): AssociativitySpec[
    A, B, MA, MB, MC]
  • lift: A procedure to lift a value to a monad.
  • f: The procedure passed to the first flatMap defined by the tested monad type.
  • g: The procedure passed to the second flatMap defined by the tested monad type.
  • runArg: The argument passed to run as defined in LazyMonad.
  Source Edit
func monadLawsSpec[LA; LMA; LMB; RT; RM; AA; AB; AMA; AMB; AMC](
    leftIdentity: LeftIdentitySpec[LA, LMA, LMB];
    rightIdentity: RightIdentitySpec[RT, RM];
    associativity: AssociativitySpec[AA, AB, AMA, AMB, AMC]): MonadLawsSpec[LA, LMA,
    LMB, RT, RM, AA, AB, AMA, AMB, AMC]
  Source Edit

Templates

template checkLeftIdentity[A; MA; MB](spec: LeftIdentitySpec[A, MA, MB]): bool

Checks whether a.lift().flatMap(f) == f(a).

Lifting a value a to a monad, and binding f to it should be the same as applying f to a.

  Source Edit
template checkRightIdentity[T; M](spec: RightIdentitySpec[T, M]): bool

Checks whether a.lift().flatMap(lift) == a.lift().

Lifting a value a, and binding the same lift procedure to it should be the same as lifting a.

  Source Edit
template checkAssociativity[A; B; MA; MB; MC](
    spec: AssociativitySpec[A, B, MA, MB, MC]): bool

Checks whether a.lift().flatMap(f).flatMap(g) == a.lift().flatMap(f.chain(m => m.flatMap(g))).

Lifting a value a, binding f, then g to it should be the same as lifting a and binding f.chain(m => m.flatMap(g)).

  Source Edit
template checkMonadLaws[LA; LMA; LMB; RT; RM; AA; AB; AMA; AMB; AMC](
    spec: MonadLawsSpec[LA, LMA, LMB, RT, RM, AA, AB, AMA, AMB, AMC]): bool
  Source Edit