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 ¶
- 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], ...) func(a A) booldeprecated
- func AssertLeftIdentity[HKTA, HKTB, A, B any](t *testing.T, eq E.Eq[HKTB], fofa func(A) HKTA, fofb func(B) HKTB, ...) func(a A) booldeprecated
- func AssertRightIdentity[HKTA, A any](t *testing.T, eq E.Eq[HKTA], fofa func(A) HKTA, ...) func(fa HKTA) booldeprecated
- func MonadAssertAssociativity[HKTA, HKTB, HKTC, HKTAB, HKTAC, HKTBC, A, B, C any](t *testing.T, eq E.Eq[HKTC], fofb pointed.Pointed[B, HKTB], ...) func(fa HKTA) bool
- 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], ...) func(a A) bool
- func MonadAssertLeftIdentity[HKTA, HKTB, HKTFAB, A, B any](t *testing.T, eq E.Eq[HKTB], fofb pointed.Pointed[B, HKTB], ...) func(a A) bool
- 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
- 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], ...)
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.