Online Book Reader

Home Category

Learn You a Haskell for Great Good! - Miran Lipovaca [115]

By Root 482 0
- 3) - 4 and 5 - (3 - 4) result in different numbers.

By being aware of these properties, we have chanced upon monoids!

The Monoid Type Class


A monoid is made up of an associative binary function and a value that acts as an identity with respect to that function. When something acts as an identity with respect to a function, it means that when called with that function and some other value, the result is always equal to that other value. 1 is the identity with respect to *, and [] is the identity with respect to ++. There are a lot of other monoids to be found in the world of Haskell, which is why the Monoid type class exists. It’s for types that can act like monoids. Let’s see how the type class is defined:

class Monoid m where

mempty :: m

mappend :: m -> m -> m

mconcat :: [m] -> m

mconcat = foldr mappend mempty

The Monoid type class is defined in import Data.Monoid. Let’s take some time to get properly acquainted with it.

First, we see that only concrete types can be made instances of Monoid, because the m in the type class definition doesn’t take any type parameters. This is different from Functor and Applicative, which require their instances to be type constructors that take one parameter.

The first function is mempty. It’s not really a function, since it doesn’t take parameters. It’s a polymorphic constant, kind of like minBound from Bounded. mempty represents the identity value for a particular monoid.

Next up, we have mappend, which, as you’ve probably guessed, is the binary function. It takes two values of the same type and returns another value of that same type. The decision to call it mappend was kind of unfortunate, because it implies that we’re appending two things in some way. While ++ does take two lists and append one to the other, * doesn’t really do any appending; it just multiplies two numbers together. When you meet other instances of Monoid, you’ll see that most of them don’t append values either. So avoid thinking in terms of appending and just think in terms of mappend being a binary function that takes two monoid values and returns a third.

The last function in this type class definition is mconcat. It takes a list of monoid values and reduces them to a single value by using mappend between the list’s elements. It has a default implementation, which just takes mempty as a starting value and folds the list from the right with mappend. Because the default implementation is fine for most instances, we won’t concern ourselves with mconcat too much. When making a type an instance of Monoid, it suffices to just implement mempty and mappend. Although for some instances, there might be a more efficient way to implement mconcat, the default implementation is just fine for most cases.

The Monoid Laws


Before moving on to specific instances of Monoid, let’s take a brief look at the monoid laws.

You’ve learned that there must be a value that acts as the identity with respect to the binary function and that the binary function must be associative. It’s possible to make instances of Monoid that don’t follow these rules, but such instances are of no use to anyone because when using the Monoid type class, we rely on its instances acting like monoids. Otherwise, what’s the point? That’s why when making monoid instances, we need to make sure they follow these laws:

mempty `mappend` x = x

x `mappend` mempty = x

(x `mappend` y) `mappend` z = x `mappend` (y `mappend` z)

The first two laws state that mempty must act as the identity with respect to mappend, and the third says that mappend must be associative (the order in which we use mappend to reduce several monoid values into one doesn’t matter). Haskell doesn’t enforce these laws, so we need to be careful that our instances do indeed obey them.

Meet Some Monoids

Now that you know what monoids are about, let’s look at some Haskell types that are monoids, what their Monoid instances look like, and their uses.

Lists Are Monoids


Yes, lists are monoids! As you’ve seen, the ++ function and the empty list [] form a

Return Main Page Previous Page Next Page

®Online Book Reader