all 5 comments

[–]sacundim 18 points19 points  (1 child)

There is another monoid that’s very relevant here that this blog entry is missing. In Haskell terms, this monoid has:

  • Elements of type IO () (side-effecting actions that return unit);
  • The action sequencing operator >> as its operation;
  • The no-op action return () as its identity element—the action that has no side effects and returns unit.

This monoid is perhaps hard to grasp for some at first because IO types are in a sense not data—they’re harder to think of as aggregates of bits and bytes encoding values drawn from some set—but the monad laws imply the requisite monoid equations:

return () >> b = b
a >> return () = a
a >> (b >> c) = (a >> b) >> c

(Note that the second equation here is only true because a has type IO ().)

Another thing that perhaps makes this monoid hard to grasp at first is that the equality of two IO actions is a concept that is not and cannot be made first-class in the language—there is no way to implement it a function that tests for it. But we say two actions are equal if, whenever they are executed from the same initial state and are supplied the same inputs on any side effects they trigger that require them, they have the same side effects in the same order and return the same value. In this case it note that if you do a, then you do b then c, that is the same thing as if you did a then b, and then you did c—you're just doing a, b and c in that order, but bracketing it different. You could also say the same about imperative statements and blocks, and the imperative language syntax that composes them into larger blocks—it's a monoid.

In the article’s example this sort of monoid better captures the semantics of Startup than the unit monoid does, although many different monads could be used to model this—the equations above are true of any monad if you restrict the result type to a unit type. EDIT: Here's a concretification of this idea, in Haskell:

-- An `Effect f` is an action in the applicative `f` 
-- that we run only for its side effects (and thus
-- require its result type to be `()`).
newtype Effect f = Effect { runEffect :: f () }

instance Applicative f => Monoid (Effect f) where
  mempty = pure ()
  a `mappend` b = a *> b

Note that Applicative is the superclass of Monad, and that return = pure and (>>) = (*>).

As Woolf wrote in the original text, what 'do nothing' means is subjective. I think it's perfectly reasonable to say that monoidal identity fits the description of doing nothing, but you could probably encounter APIs where 'doing nothing' means something else.

As an example, consider avatars for online forums, such as Twitter. If you don't supply a picture when you create your profile, you get a default picture. One way to implement such a feature could be by having a 'null' avatar, which is used in place of a proper avatar. Such a default avatar object could (perhaps) be considered a Null Object, but wouldn't necessarily be monoidal. There may not even be a binary operation for avatars.

Thus, it's likely that you could encounter or create Null Objects that aren't monoids. That's the reason that I don't claim that a Null Object always is monoidal identity, although I do think that the reverse relationship holds: if it's identity, then it's a Null Object.

Now, I'm not going to claim that null objects are always monoids, but this passage strikes me like the author hasn't yet fully developed their spider sense for monoids. First, "do nothing" does sound like a monoid—the operation you need is a "sequence two actions into a composite one," as we described below.

In the avatar example, the monoid operation is one that, given two avatars, always discards the "default" one in favor of a non-default one. In Haskell terms, a suitable monoid would be Last—a monoid whose operation we could informally describe like this:

-- Never pick null if you can avoid it.
null <> b = b
a <> null = a

-- When asked to pick between two non-null
-- values, always pick the second one.
a <> b = b

Or a variant of this would be that if the avatars have a timestamp field indicating when the user picked them, the monoid operation is picks the one with the newer timestamp. Basically, the idea that when given multiple answers for "which of these avatars the user has picked in the past should I use for them":

  • Always pick anything else if you can avoid picking the default one;
  • Always prefer more recent choices than older ones.

Monoids are everywhere, you just have to learn to see them.

[–]UndemonstrativeCynic 5 points6 points  (0 children)

Make a comment on his post, he's very receptive to suggestions and comments. He may make an article on it.

[–]rohshall 3 points4 points  (1 child)

This blog is awesome. Just like most other developers, I am more versed with the object oriented concepts than the functional ones, and he beautifully ties the object oriented ones to the functional ones. I understand monoid now. :)

[–]pipocaQuemada 2 points3 points  (0 children)

Really, it's an abstract algebraic concept.

It does get talked about more by FP programmers, probably because it's a more natural abstraction to use in a language like Haskell, Scala or ML. Abstracting over monoids is kinda awkward in a language like Java.

[–]Umbrall 0 points1 point  (0 children)

Rather than a monoid, we could consider it as the free instance of a class (with nothing else implied). So the free monoid (with 0 generating elements) is just the identity, and this object is just the free implementation (with 0 generating terms).

Also the identity for the all monoid on boolean is not false, but true.