Semigroup instances are required to satisfy the second law but with
'()' instead of mappend. Additionally, if the type s has
any algebraic structure, act m should be a homomorphism. For
example, if s is also a monoid we should have act m mempty =
mempty and act m (s1 `mappend` s2) = (act m s1) `mappend`
(act m s2).

By default, act = const id, so for a type M which should have
no action on anything, it suffices to write

instance Action M s

with no method implementations.

It is a bit awkward dealing with instances of Action, since it
is a multi-parameter type class but we can't add any functional
dependencies---the relationship between monoids and the types on
which they act is truly many-to-many. In practice, this library
has chosen to have instance selection for Action driven by the
first type parameter. That is, you should never write an
instance of the form Action m SomeType since it will overlap
with instances of the form Action SomeMonoid t. Newtype
wrappers can be used to (awkwardly) get around this.