testing

package
v2.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 20, 2025 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package testing provides law-based testing utilities for monads.

This package implements property-based tests for the three fundamental monad laws:

  • Left Identity: Chain(f)(Of(a)) == f(a)
  • Right Identity: Chain(Of)(m) == m
  • Associativity: Chain(g)(Chain(f)(m)) == Chain(x => Chain(g)(f(x)))(m)

Additionally, it validates that monads satisfy all prerequisite laws from:

  • Functor (identity, composition)
  • Apply (composition)
  • Applicative (identity, homomorphism, interchange)
  • Chainable (associativity)

Usage:

func TestMyMonad(t *testing.T) {
    // Set up equality checkers
    eqa := eq.FromEquals[Option[int]](...)
    eqb := eq.FromEquals[Option[string]](...)
    eqc := eq.FromEquals[Option[float64]](...)

    // Set up monad instances
    maa := &optionMonad[int, int]{}
    mab := &optionMonad[int, string]{}
    // ... etc

    // Run the law tests
    lawTest := MonadAssertLaws(t, eqa, eqb, eqc, ...)
    assert.True(t, lawTest(42))
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AssertLaws deprecated

func AssertLaws[HKTA, HKTB, HKTC, HKTAA, HKTAB, HKTBC, HKTAC, HKTABB, HKTABAC, A, B, C any](t *testing.T,
	eqa E.Eq[HKTA],
	eqb E.Eq[HKTB],
	eqc E.Eq[HKTC],

	fofa func(A) HKTA,
	fofb func(B) HKTB,
	fofc func(C) HKTC,

	fofaa func(func(A) A) HKTAA,
	fofab func(func(A) B) HKTAB,
	fofbc func(func(B) C) HKTBC,
	fofabb func(func(func(A) B) B) HKTABB,

	faa func(HKTA, func(A) A) HKTA,
	fab func(HKTA, func(A) B) HKTB,
	fac func(HKTA, func(A) C) HKTC,
	fbc func(HKTB, func(B) C) HKTC,

	fmap func(HKTBC, func(func(B) C) func(func(A) B) func(A) C) HKTABAC,

	chainaa func(HKTA, func(A) HKTA) HKTA,
	chainab func(HKTA, func(A) HKTB) HKTB,
	chainac func(HKTA, func(A) HKTC) HKTC,
	chainbc func(HKTB, func(B) HKTC) HKTC,

	fapaa func(HKTAA, HKTA) HKTA,
	fapab func(HKTAB, HKTA) HKTB,
	fapbc func(HKTBC, HKTB) HKTC,
	fapac func(HKTAC, HKTA) HKTC,

	fapabb func(HKTABB, HKTAB) HKTB,
	fapabac func(HKTABAC, HKTAB) HKTAC,

	ab func(A) B,
	bc func(B) C,
) func(a A) bool

AssertLaws tests all monad laws including prerequisite laws from Functor, Apply, Applicative, and Chainable.

This function validates:

  • Functor laws: identity, composition
  • Apply law: composition
  • Applicative laws: identity, homomorphism, interchange
  • Chainable law: associativity
  • Monad laws: left identity, right identity

The monad laws build upon and require all the prerequisite laws to hold.

Deprecated: use MonadAssertLaws instead

func AssertLeftIdentity deprecated

func AssertLeftIdentity[HKTA, HKTB, A, B any](t *testing.T,
	eq E.Eq[HKTB],

	fofa func(A) HKTA,
	fofb func(B) HKTB,

	fchain func(HKTA, func(A) HKTB) HKTB,

	ab func(A) B,
) func(a A) bool

AssertLeftIdentity tests the monad left identity law: M.chain(M.of(a), f) <-> f(a)

This law ensures that lifting a value into the monad and immediately chaining a function over it is equivalent to just applying the function directly.

Deprecated: use MonadAssertLeftIdentity instead

func AssertRightIdentity deprecated

func AssertRightIdentity[HKTA, A any](t *testing.T,
	eq E.Eq[HKTA],

	fofa func(A) HKTA,

	fchain func(HKTA, func(A) HKTA) HKTA,
) func(fa HKTA) bool

AssertRightIdentity tests the monad right identity law: M.chain(fa, M.of) <-> fa

This law ensures that chaining a monadic value with the Of (pure/return) function returns the original monadic value unchanged.

Deprecated: use MonadAssertRightIdentity instead

func MonadAssertAssociativity

func MonadAssertAssociativity[HKTA, HKTB, HKTC, HKTAB, HKTAC, HKTBC, A, B, C any](
	t *testing.T,
	eq E.Eq[HKTC],
	fofb pointed.Pointed[B, HKTB],
	fofc pointed.Pointed[C, HKTC],
	mab monad.Monad[A, B, HKTA, HKTB, HKTAB],
	mac monad.Monad[A, C, HKTA, HKTC, HKTAC],
	mbc monad.Monad[B, C, HKTB, HKTC, HKTBC],
	ab func(A) B,
	bc func(B) C,
) func(fa HKTA) bool

MonadAssertAssociativity is a convenience function that tests only the monad associativity law (which is inherited from Chainable).

Associativity Law:

Chain(g)(Chain(f)(m)) == Chain(x => Chain(g)(f(x)))(m)

This law ensures that the order in which we nest chain operations doesn't matter, as long as the sequence of operations remains the same.

Example:

// For Option monad:
f := func(x int) Option[string] { return Some(strconv.Itoa(x)) }
g := func(s string) Option[float64] { return Some(parseFloat(s)) }
m := Some(42)

// These should be equal:
Chain(g)(Chain(f)(m))                    // Some(42.0)
Chain(func(x int) { Chain(g)(f(x)) })(m) // Some(42.0)

Type Parameters:

  • A, B, C: Value types for the transformation chain
  • HKTA, HKTB, HKTC: Higher-kinded types containing A, B, C
  • HKTAB, HKTAC, HKTBC: Higher-kinded types containing functions

func MonadAssertLaws

func MonadAssertLaws[HKTA, HKTB, HKTC, HKTAA, HKTAB, HKTBC, HKTAC, HKTABB, HKTABAC, A, B, C any](t *testing.T,
	eqa E.Eq[HKTA],
	eqb E.Eq[HKTB],
	eqc E.Eq[HKTC],

	fofc pointed.Pointed[C, HKTC],
	fofaa pointed.Pointed[func(A) A, HKTAA],
	fofbc pointed.Pointed[func(B) C, HKTBC],
	fofabb pointed.Pointed[func(func(A) B) B, HKTABB],

	fmap functor.Functor[func(B) C, func(func(A) B) func(A) C, HKTBC, HKTABAC],

	fapabb applicative.Applicative[func(A) B, B, HKTAB, HKTB, HKTABB],
	fapabac applicative.Applicative[func(A) B, func(A) C, HKTAB, HKTAC, HKTABAC],

	maa monad.Monad[A, A, HKTA, HKTA, HKTAA],
	mab monad.Monad[A, B, HKTA, HKTB, HKTAB],
	mac monad.Monad[A, C, HKTA, HKTC, HKTAC],
	mbc monad.Monad[B, C, HKTB, HKTC, HKTBC],

	ab func(A) B,
	bc func(B) C,
) func(a A) bool

MonadAssertLaws validates all monad laws and prerequisite laws for a monad implementation.

This is the primary testing function for verifying monad implementations. It checks:

Monad Laws (primary):

  • Left Identity: Chain(f)(Of(a)) == f(a)
  • Right Identity: Chain(Of)(m) == m
  • Associativity: Chain(g)(Chain(f)(m)) == Chain(x => Chain(g)(f(x)))(m)

Prerequisite Laws (inherited from parent type classes):

  • Functor: identity, composition
  • Apply: composition
  • Applicative: identity, homomorphism, interchange
  • Chainable: associativity

Usage:

func TestOptionMonad(t *testing.T) {
    // Create equality checkers
    eqa := eq.FromEquals[Option[int]](optionEq[int])
    eqb := eq.FromEquals[Option[string]](optionEq[string])
    eqc := eq.FromEquals[Option[float64]](optionEq[float64])

    // Define test functions
    ab := strconv.Itoa
    bc := func(s string) float64 { v, _ := strconv.ParseFloat(s, 64); return v }

    // Create monad instances and other required type class instances
    // ... (setup code)

    // Run the law tests
    lawTest := MonadAssertLaws(t, eqa, eqb, eqc, ...)
    assert.True(t, lawTest(42))
}

Type Parameters:

  • A, B, C: Value types for testing transformations
  • HKTA, HKTB, HKTC: Higher-kinded types containing A, B, C
  • HKTAA, HKTAB, HKTBC, HKTAC: Higher-kinded types containing functions
  • HKTABB, HKTABAC: Higher-kinded types for applicative testing

func MonadAssertLeftIdentity

func MonadAssertLeftIdentity[HKTA, HKTB, HKTFAB, A, B any](t *testing.T,
	eq E.Eq[HKTB],

	fofb pointed.Pointed[B, HKTB],

	ma monad.Monad[A, B, HKTA, HKTB, HKTFAB],

	ab func(A) B,
) func(a A) bool

MonadAssertLeftIdentity tests the monad left identity law: M.chain(M.of(a), f) <-> f(a)

This law states that wrapping a value with Of and immediately chaining with a function f should be equivalent to just applying f to the value directly.

In other words: lifting a value into the monad and then binding over it should have the same effect as just applying the function.

Example:

// For Option monad with value 42 and function f(x) = Some(toString(x)):
Chain(f)(Of(42)) == f(42)
// Both produce: Some("42")

Type Parameters:

  • A: Input value type
  • B: Output value type
  • HKTA: Higher-kinded type containing A
  • HKTB: Higher-kinded type containing B
  • HKTFAB: Higher-kinded type containing function A -> B

func MonadAssertRightIdentity

func MonadAssertRightIdentity[HKTA, HKTAA, A any](t *testing.T,
	eq E.Eq[HKTA],

	ma monad.Monad[A, A, HKTA, HKTA, HKTAA],

) func(fa HKTA) bool

MonadAssertRightIdentity tests the monad right identity law: M.chain(fa, M.of) <-> fa

This law states that chaining a monadic value with the Of (pure/return) function should return the original monadic value unchanged. This ensures that Of doesn't add any additional structure or effects beyond what's already present.

Example:

// For Option monad with value Some(42):
Chain(Of)(Some(42)) == Some(42)
// The value remains unchanged

Type Parameters:

  • A: The value type
  • HKTA: Higher-kinded type containing A
  • HKTAA: Higher-kinded type containing function A -> A

func TestMonadLaws

func TestMonadLaws[HKTA, HKTB, HKTC, HKTAA, HKTAB, HKTBC, HKTAC, HKTABB, HKTABAC, A, B, C any](
	t *testing.T,
	name string,
	testValues []A,
	eqa E.Eq[HKTA],
	eqb E.Eq[HKTB],
	eqc E.Eq[HKTC],
	fofc pointed.Pointed[C, HKTC],
	fofaa pointed.Pointed[func(A) A, HKTAA],
	fofbc pointed.Pointed[func(B) C, HKTBC],
	fofabb pointed.Pointed[func(func(A) B) B, HKTABB],
	fmap functor.Functor[func(B) C, func(func(A) B) func(A) C, HKTBC, HKTABAC],
	fapabb applicative.Applicative[func(A) B, B, HKTAB, HKTB, HKTABB],
	fapabac applicative.Applicative[func(A) B, func(A) C, HKTAB, HKTAC, HKTABAC],
	maa monad.Monad[A, A, HKTA, HKTA, HKTAA],
	mab monad.Monad[A, B, HKTA, HKTB, HKTAB],
	mac monad.Monad[A, C, HKTA, HKTC, HKTAC],
	mbc monad.Monad[B, C, HKTB, HKTC, HKTBC],
	ab func(A) B,
	bc func(B) C,
)

TestMonadLaws is a helper function that runs all monad law tests with common test values.

This is a convenience wrapper around MonadAssertLaws that runs the law tests with a set of test values and reports the results. It's useful for quick testing with standard inputs.

Parameters:

  • t: The testing.T instance
  • name: A descriptive name for this test suite
  • testValues: A slice of values of type A to test with
  • Other parameters: Same as MonadAssertLaws

Example:

func TestOptionMonadLaws(t *testing.T) {
    testValues := []int{0, 1, -1, 42, 100}
    TestMonadLaws(t, "Option[int]", testValues, eqa, eqb, eqc, ...)
}

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL