drathier / elm-test-tables / Expect.Category

Expect.Category provides expectations for common properties of binary functions, like (a+b)+c = a+(b+c) or a+b = b+a:

fuzz3 int int int "+" <|
    \a b c ->
        { f = (+), a = a, b = b, c = c }
            |> Expect.all [ associative, commutative ]

These mathematical properties are actually quite useful, so try to follow a few of them for whatever data type you're building.

How to use this module

The function signatures in this module are horrible. Sorry about that. Here's how I intend the functions to be used:

fuzz3 int int int "+" <|
    \a b c ->
        { f = (+), a = a, b = b, c = c }
            |> Expect.all [ identityElement 0, associative, commutative ]

or

fuzz3 appendable appendable appendable "++" <|
    \a b c ->
        { f = (++), a = a, b = b, c = c }
            |> Expect.all [ associative ]

The properties to choose from

associative : { r | f : a -> a -> a, a : a, b : a, c : a } -> Expectation

Associativity is the property that (a ⊕ b) ⊕ c = a ⊕ (b ⊕ c), or f (f a b) c = f a (f b c), for some infix operator , or binary function f.

Notable examples include +, * and max, but note that float operations generally aren't associative.

commutative : { r | f : a -> a -> a, a : a, b : a } -> Expectation

Commutativity is the property that a ⊕ b = b ⊕ a, or f a b = f b a, for some infix operator , or binary function f.

Notable examples include +, * and max.

idempotent : { r | f : a -> a -> a, a : a } -> Expectation

Idempotence is the property that a ⊕ a = a, or f a a = a, for some infix operator , or binary function f.

Notable examples include Bitwise.or, Bitwise.and and max.

identityElement : a -> { r | f : a -> a -> a, a : a } -> Expectation

The identity element is the element e such that a ⊕ e = e ⊕ a = a, or f e a = f a e = a, for some infix operator , or binary function f.

Notable examples include 0 for +, 1 for * and 0 for Bitwise.or.

zeroElement : a -> { r | f : a -> a -> a, a : a } -> Expectation

The zero element is the element 0 such that a ⊕ 0 = 0 ⊕ a = 0, or f 0 a = f a 0 = 0, for some infix operator , or binary function f.

Notable examples include 0 for *, Infinity for max and 0 for Bitwise.and.