// Setoid a.equals(a) === true // reflexivity a.equals(b) === b.equals(a) // summetry a.equals(b) && b.equals(c) == q.equals(c) // transitivity // Ord // must also implement the Setoid a.lte(b) || b.lte(a) === true // totality a.lte(b) && a.lte(a) == a.equals(b) // antisymmetry a.lte(b) && b.lte(c) == a.lte(c) // transitivity // Semigroupoid a.compose(b).compose(c) === a.compose(b.compose(c)) // associativity // Category // must also implement the Semigroupoid a.compose(C.id()) === a // right identity C.id().compose(a) === a // left identity // Semigroup a.concat(b).concat(c) === a.concat(b.concat(c)) // associativity // Monoid // must also implement the Semigroup m.concat(M.empty()) === m // right identity M.empty().concat(m) === m // left identity // Group // must also implement the Monoid g.concat(g.invert()) == G.empty() // right inverse g.invert().concat(g) == G.empty() // left inverse // Filterable v.filter(x => p(x) && q(x)) == v.filter(p).filter(q) // distributivity v.filter(x => true) = v // identity v.filter(x => false) == w.filter(x => false) // annihilation // Functor u.map(a => a) == u // identity u.map(x => f(g(x))) == u.map(g).map(f) // composition // Contravariant u.contramap(a => a) == u // identity u.contramap(x => f(g(x))) == u.contramap(f).contramap(g) // composition