Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an example using foldMap on to a tuple #517

Merged
merged 1 commit into from
Sep 3, 2015
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 45 additions & 10 deletions docs/src/main/tut/monoid.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@ source: "https://github.com/non/algebra/blob/master/core/src/main/scala/algebra/
---
# Monoid

`Monoid` extends the [`Semigroup`](semigroup.html) typeclass, adding an `empty` method to semigroup's
`combine`. The `empty` method must return a value that when combined with any other instance of that type
returns the other instance, i.e.
`Monoid` extends the [`Semigroup`](semigroup.html) type class, adding an
`empty` method to semigroup's `combine`. The `empty` method must return a
value that when combined with any other instance of that type returns the
other instance, i.e.

(combine(x, empty) == combine(empty, x) == x)

For example, if we have a `Monoid[String]` with `combine` defined as string concatenation, then `empty = ""`.
For example, if we have a `Monoid[String]` with `combine` defined as string
concatenation, then `empty = ""`.

Having an `empty` defined allows us to combine all the elements of some potentially empty collection
of `T` for which a `Monoid[T]` is defined and return a `T`, rather than an `Option[T]` as we have a
sensible default to fall back to.
Having an `empty` defined allows us to combine all the elements of some
potentially empty collection of `T` for which a `Monoid[T]` is defined and
return a `T`, rather than an `Option[T]` as we have a sensible default to
fall back to.

```tut
import cats._
Expand All @@ -28,8 +31,9 @@ Monoid[String].combineAll(List("a", "b", "c"))
Monoid[String].combineAll(List())
```

The advantage of using these typeclass provided methods, rather than the specific ones for each
type, is that we can compose monoids to allow us to operate on more complex types, e.g.
The advantage of using these type class provided methods, rather than the
specific ones for each type, is that we can compose monoids to allow us to
operate on more complex types, e.g.

```tut
import cats._
Expand All @@ -38,9 +42,40 @@ import cats.std.all._
Monoid[Map[String,Int]].combineAll(List(Map("a" -> 1, "b" -> 2), Map("a" -> 3)))
Monoid[Map[String,Int]].combineAll(List())
```

This is also true if we define our own instances. As an example, let's use
[`Foldable`](foldable.html)'s `foldMap`, which maps over values accumulating
the results, using the available `Monoid` for the type mapped onto. To use this
with a function that produces a tuple, we can define a `Monoid` for a tuple
that will be valid for any tuple where the types it contains also have a
`Monoid` available:

```tut
import cats._
import cats.implicits._

val l = List(1, 2, 3, 4, 5)

l.foldMap(identity)
l.foldMap(i => i.toString)

implicit def tupleMonoid[A : Monoid, B : Monoid]: Monoid[(A, B)] =
new Monoid[(A, B)] {
def combine(x: (A, B), y: (A, B)): (A, B) = {
val (xa, xb) = x
val (ya, yb) = y
(Monoid[A].combine(xa, ya), Monoid[B].combine(xb, yb))
}
def empty: (A, B) = (Monoid[A].empty, Monoid[B].empty)
}

l.foldMap(i => (i, i.toString)) // do both of the above in one pass, hurrah!
```

-------------------------------------------------------------------------------

N.B.
Cats does not define a `Monoid` typeclass itself, it uses the [`Monoid`
Cats does not define a `Monoid` type class itself, it uses the [`Monoid`
trait](https://github.com/non/algebra/blob/master/core/src/main/scala/algebra/Monoid.scala)
which is defined in the [algebra project](https://github.com/non/algebra) on
which it depends. The [`cats` package object](https://github.com/non/cats/blob/master/core/src/main/scala/cats/package.scala)
Expand Down