### 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))`