This is known as a lax monoidal functor. I highly recommend you read this paper which shows how Applicatives are one type of lax monoid and you can reformulate your type as an Applicative
and get an equivalent interface:
instance Applicative Stuff where
pure a = Stuff a 0
(Stuff f m) <*> (Stuff x n) = Stuff (f x) (m + n)
tmappend :: (Applicative f) => f a -> f b -> f (a, b)
tmappend fa fb = (,) <$> fa <*> fb
tzero :: (Applicative f) => f ()
tzero = pure ()
Notice that tmappend
and tzero
work for all Applicative
s, not just Stuff
. The paper I linked discusses this idiom in more detail.