Skip to content

Instantly share code, notes, and snippets.

@JoolsF
Last active April 28, 2018 16:43
Show Gist options
  • Select an option

  • Save JoolsF/b1f92a7957b4ea91ae2c569f11d0912e to your computer and use it in GitHub Desktop.

Select an option

Save JoolsF/b1f92a7957b4ea91ae2c569f11d0912e to your computer and use it in GitHub Desktop.
monoid example 1
/**
* A monoid is a type with a combine operation of type (A, A) => A
* and an identity operation of type A
*
* Note that a semgigroup is just the combine part of a Monoid.
* Here we have split the type up into traits as some types
* for which we cannot define an identity element.
*/
trait Semigroup[A] {
def combine(x: A, y: A): A
}
trait Monoid[A] extends Semigroup[A] {
def empty: A
}
object Monoid {
def apply[A](implicit monoid: Monoid[A]) =
monoid
}
/**
* It follows the following laws.
* It must be associative and follow the identity law
*/
def associativeLaw[A](x: A, y: A, z: A)
(implicit m: Monoid[A]): Boolean = {
m.combine(x, m.combine(y, z)) ==
m.combine(m.combine(x, y), z)
}
def identityLaw[A](x: A)
(implicit m: Monoid[A]): Boolean = {
(m.combine(x, m.empty) == x) &&
(m.combine(m.empty, x) == x)
}
object BooleanMonoidInstances {
implicit def and = new Monoid[Boolean] {
override def combine(x: Boolean, y: Boolean): Boolean = x && y
override def empty: Boolean = true
}
implicit def or = new Monoid[Boolean] {
override def combine(x: Boolean, y: Boolean): Boolean = x || y
override def empty: Boolean = false
}
implicit def xor = new Monoid[Boolean] {
override def combine(x: Boolean, y: Boolean): Boolean = x ^ y
override def empty: Boolean = false
}
}
/**
* Monoids in cats
*/
import cats.Monoid
import cats.Semigroup
import cats.instances.string._
Monoid[String].combine("hello ","world ") // hello world
Monoid[String].empty // ""
// if we dont need empty we can write
Semigroup[String].combine("hello ","world ")
// we can assemble a Monoid[Option[String]] as follows
import cats.instances.option._
Monoid[Option[String]].combine(None, Some("hello world")) //Some(hello world)
// syntax
import cats.syntax.semigroup._ //for the |+| syntax
import cats.instances.int._
1 |+| 2 |+| 3 |+| Monoid[Int].empty // 6
import cats.Monoid
import cats.instances.string._
Monoid[String].combine("hello ", "world ") // hello world
Monoid[String].empty // ""
// if we dont need empty we can write
import cats.Semigroup
Semigroup[String].combine("hello ", "world ")
// we can assemble a Monoid[Option[String]] as follows
import cats.instances.option._
Monoid[Option[String]].combine(None, Some("hello world")) //Some(hello world)
// syntax
import cats.syntax.semigroup._ // for |+|
import cats.instances.int._
1 |+| 2 |+| 3 |+| Monoid[Int].empty // 6
import cats.instances.map._ // for Monoid
val map1 = Map("a" -> 1, "b" -> 2)
val map2 = Map("b" -> 3, "d" -> 4)
map1 |+| map2
// res3: Map[String,Int] = Map(b -> 5, d -> 4, a -> 1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment