Online Book Reader

Home Category

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

By Root 516 0
Sum 3

3

ghci> getSum . mconcat . map Sum $ [1,2,3]

6

Any and All


Another type that can act like a monoid in two distinct but equally valid ways is Bool. The first way is to have the function ||, which represents a logical OR, act as the binary function along with False as the identity value. With the logical OR, if any of the two parameters is True, it returns True; otherwise, it returns False. So if we use False as the identity value, OR will return False when used with False and True when used with True. The Any newtype constructor is an instance of Monoid in this fashion. It’s defined like this:

newtype Any = Any { getAny :: Bool }

deriving (Eq, Ord, Read, Show, Bounded)

Its instance looks like this:

instance Monoid Any where

mempty = Any False

Any x `mappend` Any y = Any (x || y)

It’s called Any because x `mappend` y will be True if any one of those two is True. Even if three or more Any wrapped Bool values are mappended together, the result will hold True if any of them are True:

ghci> getAny $ Any True `mappend` Any False

True

ghci> getAny $ mempty `mappend` Any True

True

ghci> getAny . mconcat . map Any $ [False, False, False, True]

True

ghci> getAny $ mempty `mappend` mempty

False

The other way for Bool to be an instance of Monoid is to kind of do the opposite: Have && be the binary function and then make True the identity value. Logical AND will return True only if both of its parameters are True.

This is the newtype declaration:

newtype All = All { getAll :: Bool }

deriving (Eq, Ord, Read, Show, Bounded)

And this is the instance:

instance Monoid All where

mempty = All True

All x `mappend` All y = All (x && y)

When we mappend values of the All type, the result will be True only if all the values used in the mappend operations are True:

ghci> getAll $ mempty `mappend` All True

True

ghci> getAll $ mempty `mappend` All False

False

ghci> getAll . mconcat . map All $ [True, True, True]

True

ghci> getAll . mconcat . map All $ [True, True, False]

False

Just as with multiplication and addition, we usually explicitly state the binary functions instead of wrapping them in newtypes and then using mappend and mempty. mconcat seems useful for Any and All, but usually it’s easier to use the or and and functions. or takes lists of Bool values and returns True if any of them are True. and takes the same values and returns True if all of them are True.

The Ordering Monoid


Remember the Ordering type? It’s used as the result when comparing things, and it can have three values: LT, EQ, and GT, which stand for less than, equal, and greater than, respectively.

ghci> 1 `compare` 2

LT

ghci> 2 `compare` 2

EQ

ghci> 3 `compare` 2

GT

With lists, numbers, and Boolean values, finding monoids was just a matter of looking at already existing commonly used functions and seeing if they exhibited some sort of monoid behavior. With Ordering, we need to look a bit harder to recognize a monoid. It turns out that the ordering Monoid instance is just as intuitive as the ones we’ve met so far, and it’s also quite useful:

instance Monoid Ordering where

mempty = EQ

LT `mappend` _ = LT

EQ `mappend` y = y

GT `mappend` _ = GT

The instance is set up like this: When we mappend two Ordering values, the one on the left is kept, unless the value on the left is EQ. If the value on the left is EQ, the right one is the result. The identity is EQ. At first, this may seem kind of arbitrary, but it actually resembles the way we alphabetically compare words. We look at the first two letters, and if they differ, we can already decide which word would go first in a dictionary. However, if the first two letters are equal, then we move on to comparing the next pair of letters and repeat the process.

For instance, when we alphabetically compare the words ox and on, we see that the first letter of each word is equal and then move on to comparing the second letter. Since x is alphabetically greater than n, we know how the words compare. To gain some understanding of EQ being the identity, note that if we were to

Return Main Page Previous Page Next Page

®Online Book Reader