- "value" is any JavaScript value, including any which have the structures defined below.
- "equivalent" is an appropriate definition of equivalence for the given value.
The definition should ensure that the two values can be safely swapped out in a program that respects abstractions. For example:
- Two lists are equivalent if they are equivalent at all indices.
- Two plain old JavaScript objects, interpreted as dictionaries, are equivalent when they are equivalent for all keys.
- Two promises are equivalent when they yield equivalent values.
- Two functions are equivalent if they yield equivalent outputs for equivalent inputs.
a.concat(b).concat(c)is equivalent toa.concat(b.concat(c))(associativity)
A value which has a Semigroup must provide a concat method. The
concat method takes one argument:
s.concat(b)
-
bmust be a value of the same Semigroup- If
bis not the same semigroup, behaviour ofconcatis unspecified.
- If
-
concatmust return a value of the same Semigroup.
A value that implements the Monoid specification must also implement the Semigroup specficiation.
m.concat(m.empty())is equivalent tom(right identity)m.empty().concat(m)is equivalent tom(left identity)
A value which has a Monoid must provide an empty method on itself or
its constructor object. The empty method takes no arguments:
m.empty()
m.constructor.empty()
emptymust return a value of the same Monoid
u.map(function(a) { return a; }))is equivalent tou(identity)u.map(function(x) { return f(g(x)); })is equivalent tou.map(g).map(f)(composition)
A value which has a Functor must provide a map method. The map
method takes one argument:
u.map(f)
-
fmust be a function,- If
fis not a function, the behaviour ofmapis unspecified. fcan return any value.
- If
-
mapmust return a value of the same Functor
A value that implements the Applicative specification must also implement the Functor specification.
A value which satisfies the specification of a Applicative does not need to implement:
- Functor's
map; derivable asfunction(f) { return this.of(f).ap(this); })}
a.of(function(a) { return a; }).ap(v)is equivalent tov(identity)a.of(function(f) { return function(g) { return function(x) { return f(g(x))}; }; }).ap(u).ap(v).ap(w)is equivalent tou.ap(v.ap(w))(composition)a.of(f).ap(a.of(x))is equivalent toa.of(f(x))(homomorphism)u.ap(a.of(y))is equivalent toa.of(function(f) { return f(y); }).ap(u)(interchange)
A value which has an Applicative must provide an ap method. The ap
method takes one argument:
a.ap(b)
-
amust be an Applicative of a function,- If
adoes not represent a function, the behaviour ofapis unspecified.
- If
-
bmust be an Applicative of any value -
apmust apply the function in Applicativeato the value in Applicativeb
A value which has an Applicative must provide an of method on itself
or its constructor object. The of method takes one argument:
a.of(b)
a.constructor.of(b)
-
ofmust provide a value of the same Applicative- No parts of
bshould be checked
- No parts of
m.chain(f).chain(g)is equivalent tom.chain(function(x) { return f(x).chain(g); })(associativity)
A value which has a Chain must provide a chain method. The chain
method takes one argument:
m.chain(f)
-
fmust be a function which returns a value- If
fis not a function, the behaviour ofchainis unspecified. fmust return a value of the same Chain
- If
-
chainmust return a value of the same Chain
A value that implements the Monad specification must also implement the Applicative and Chain specifications.
A value which satisfies the specification of a Monad does not need to implement:
- Applicative's
ap; derivable asfunction(m) { return this.chain(function(f) { return m.map(f); }); } - Functor's
map; derivable asfunction(f) { var m = this; return m.chain(function(a) { return m.of(f(a)); })}
m.of(a).chain(f)is equivalent tof(a)(left identity)m.chain(m.of)is equivalent tom(right identity)