### Setoid 1. `S.equals(a, a) = true` (reflexivity) 2. `S.equals(a, b) = S.equals(b, a)` (symmetry) 3. If `S.equals(a, b)` and `S.equals(b, c)`, then `S.equals(a, c)` (transitivity) ### Semigroup 1. `S.concat(S.concat(a, b), c)` is equivalent to `S.concat(a, S.concat(b, c))` (associativity) ### Monoid 1. `M.concat(a, M.empty())` is equivalent to `a` (right identity) 2. `M.concat(M.empty(), a)` is equivalent to `a` (left identity) ### Functor 1. `F.map(x => x, a)` is equivalent to `a` (identity) 2. `F.map(x => f(g(x)), a)` is equivalent to `F.map(f, F.map(g, a))` (composition) ### Apply 1. `A.ap(A.ap(A.map(f => g => x => f(g(x)), a), b), c)` is equivalent to `A.ap(a, A.ap(b, c))` (composition) ### Applicative 1. `A.ap(A.of(x => x), a)` is equivalent to `a` (identity) 2. `A.ap(A.of(f), A.of(x))` is equivalent to `A.of(f(x))` (homomorphism) 3. `A.ap(a, A.of(x))` is equivalent to `A.ap(A.of(f => f(x)), a)` (interchange) ### Foldable 1. `F.reduce(f, seed, a)` is equivalent to `toArray(a).reduce(f, seed)` 2. `toArray` derivable as `a => F.reduce((r, i) => r.concat([i]), [], a)` ### Traversable 1. `t(T.sequence(A1.of, a))` is equivalent to `T.sequence(A2.of, T.map(t, a))` where `t` is a natural transformation from `A1` to `A2` (naturality) 2. `T.sequence(Id.of, T.map(Id.of, a))` is equivalent to `Id.of(a)` (identity) 3. `T.sequence(Compose.of, T.map(Compose.of, a))` is equivalent to `Compose.of(A1.map(x => T.sequence(A2.of, x), T.sequence(A1.of, a)))` (composition) ### Chain 1. `C.chain(g, C.chain(f, a))` is equivalent to `C.chain(x => C.chain(g, f(x)), a)` (associativity) ### Monad 1. `M.chain(f, M.of(x))` is equivalent to `f(x)` (left identity) 2. `M.chain(M.of, a)` is equivalent to `a` (right identity) ### Extend 1. `E.extend(f, E.extend(g, a))` is equivalent to `E.extend(x => f(E.extend(g, x)), a)` ### Comonad 1. `C.extend(C.extract, a)` is equivalent to `a` 2. `C.extract(C.extend(f, a))` is equivalent to `f(a)` 3. `C.extend(f, a)` is equivalent to `C.map(f, C.extend(x => x, a))`