Monoids

12
Monoids Monoids Piyush Mishra Software Consultant Knoldus Software LLP Piyush Mishra Software Consultant Knoldus Software LLP

description

Monoids are the certain common pattern followed by the various data types of a programming language. They are the simple algebraic structure governed by certain laws. A  simple monoid consists of a associative operation and an identity element and they can be implemented in the form of trait in scala.

Transcript of Monoids

Page 1: Monoids

MonoidsMonoids

Piyush MishraSoftware Consultant

Knoldus Software LLP

Piyush MishraSoftware Consultant

Knoldus Software LLP

Page 2: Monoids

Topics CoveredTopics CoveredWhat is Monoid

Formal definition of a Monoid

Define a String Monoid

Define a Int Monoid

Define a List Monoid

Fold lists with Monoids

What is Monoid

Formal definition of a Monoid

Define a String Monoid

Define a Int Monoid

Define a List Monoid

Fold lists with Monoids

Page 3: Monoids

What is MonoidWhat is MonoidMonoids are certain common patterns followed by the algebras of various data types of a programming language .

Integers with addition. We know that (a+b)+c == a+(b+c) and 0+n == n+0 == n

same with multiplication: (a*b)*c == a*(b*c) and 1*n == n*1 == n

Strings with concatenation. a+(b+c)==(a+b)+c; ""+s==s and s+"" == s, etc.

Lists with concatenation, like List(1,2)+List(3,4) == List(1,2,3,4)

Sets with their union, like Set(1,2,3)+Set(2,4) == Set(1,2,3,4).

This + binary operation is the common pattern.

Monoids are certain common patterns followed by the algebras of various data types of a programming language .

Integers with addition. We know that (a+b)+c == a+(b+c) and 0+n == n+0 == n

same with multiplication: (a*b)*c == a*(b*c) and 1*n == n*1 == n

Strings with concatenation. a+(b+c)==(a+b)+c; ""+s==s and s+"" == s, etc.

Lists with concatenation, like List(1,2)+List(3,4) == List(1,2,3,4)

Sets with their union, like Set(1,2,3)+Set(2,4) == Set(1,2,3,4).

This + binary operation is the common pattern.

Page 4: Monoids

Formal definition of a monoidFormal definition of a monoidGiven a type A, a binary operation Op:(A,A) => A, and an instance Zero: A, with the properties that will be specified below, the triple (A, Op, Zero) is called a monoid. Here are the properties:

Neutral or identity element : Zero `Op` a == a `Op` Zero == aAssociativity: (a `Op` b) `Op` c == a `Op` (b `Op` c)

We can express this with a Scala trait:

trait Monoid[A] {def op(a1: A, a2: A): Adef zero: A}

Given a type A, a binary operation Op:(A,A) => A, and an instance Zero: A, with the properties that will be specified below, the triple (A, Op, Zero) is called a monoid. Here are the properties:

Neutral or identity element : Zero `Op` a == a `Op` Zero == aAssociativity: (a `Op` b) `Op` c == a `Op` (b `Op` c)

We can express this with a Scala trait:

trait Monoid[A] {def op(a1: A, a2: A): Adef zero: A}

Page 5: Monoids

Define a String monoidDefine a String monoid

trait BaseMonoid[A] { def op(a: A, b: A): A def zero: A}

class StringMonoid extends BaseMonoid[String] { def op(a: String, b: String) = (a.trim + " " + b.trim).trim def zero = ""}

Here we a operation (op) in which we adding two string with space delimiter.

trait BaseMonoid[A] { def op(a: A, b: A): A def zero: A}

class StringMonoid extends BaseMonoid[String] { def op(a: String, b: String) = (a.trim + " " + b.trim).trim def zero = ""}

Here we a operation (op) in which we adding two string with space delimiter.

Page 6: Monoids

Define a Int monoidDefine a Int monoid

trait BaseMonoid[A] { def op(a: A, b: A): A def zero: A}

class IntegerMonoid extends BaseMonoid[Int] { def op(a: Int, b: Int) = a + b def zero = 0}

Here we a operation (op) in which we sum two two integer

trait BaseMonoid[A] { def op(a: A, b: A): A def zero: A}

class IntegerMonoid extends BaseMonoid[Int] { def op(a: Int, b: Int) = a + b def zero = 0}

Here we a operation (op) in which we sum two two integer

Page 7: Monoids

Define a List monoidDefine a List monoid

trait BaseMonoid[A] { def op(a: A, b: A): A def zero: A}

class ListMonoid[A] extends BaseMonoid[List[A]] { def op(a: List[A], b: List[A]): List[A] = a ++ b def zero = Nil}

Here we a operation (op) in which we adding two two Lists

trait BaseMonoid[A] { def op(a: A, b: A): A def zero: A}

class ListMonoid[A] extends BaseMonoid[List[A]] { def op(a: List[A], b: List[A]): List[A] = a ++ b def zero = Nil}

Here we a operation (op) in which we adding two two Lists

Page 8: Monoids

Folding a list with a monoidFolding a list with a monoid

def foldRight(z: A)(f: (A, A) => A): Adef foldLeft(z: A)(f: (A, A) => A): A

val words = List("hello", "world", "Whats Up")

scala> val s = words.foldRight(stringMonoid.zero)(stringMonoid.op)s: String = "hello world Whats Up"scala> val t = words.foldLeft(stringMonoid.zero)(stringMonoid.op)t: String = "hello world Whats Up"

def foldRight(z: A)(f: (A, A) => A): Adef foldLeft(z: A)(f: (A, A) => A): A

val words = List("hello", "world", "Whats Up")

scala> val s = words.foldRight(stringMonoid.zero)(stringMonoid.op)s: String = "hello world Whats Up"scala> val t = words.foldLeft(stringMonoid.zero)(stringMonoid.op)t: String = "hello world Whats Up"

Page 9: Monoids

Function which folds a list with a monoid

Function which folds a list with a monoid

def concatenate[A](as: List[A], m: Monoid[A]): A

def concatenate[A](as: List[A], m: BaseMonoid[A]): A = as.foldRight(m.zero)(m.op)

def concatenate[A](as: List[A], m: Monoid[A]): A

def concatenate[A](as: List[A], m: BaseMonoid[A]): A = as.foldRight(m.zero)(m.op)

Page 10: Monoids

Operation using different monoids instance

Operation using different monoids instance

def foldMap[A,B](as: List[A], m: Monoid[B])(f: A => B): B

def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B = as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))

def foldMap[A,B](as: List[A], m: Monoid[B])(f: A => B): B

def foldMap[A, B](as: List[A], m: Monoid[B])(f: A => B): B = as.foldLeft(m.zero)((b, a) => m.op(b, f(a)))

Page 11: Monoids

Manipulate a json using monoidManipulate a json using monoid val json = """{"first": "John","last": "Doe", "credit_card": 5105105105105100,"ssn": "123-45-6789","salary": 70000, "registered": true }"""

class JsonMonoid extends Monoid[String] { val CREDIT_CARD_REGEX = "\\b\\d{13,16}\\b" val SSN_REGEX = "\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b" val BLOCK_TEXT = "*********"

def identity = "" def op(a1: String, a2: String) = a1 + a2.replaceAll(CREDIT_CARD_REGEX, BLOCK_TEXT).replaceAll(SSN_REGEX, BLOCK_TEXT) + "," }

val monoid = new JsonMonoid val result = json.split(',').foldLeft(monoid.identity)(monoid.op)

val json = """{"first": "John","last": "Doe", "credit_card": 5105105105105100,"ssn": "123-45-6789","salary": 70000, "registered": true }"""

class JsonMonoid extends Monoid[String] { val CREDIT_CARD_REGEX = "\\b\\d{13,16}\\b" val SSN_REGEX = "\\b[0-9]{3}-[0-9]{2}-[0-9]{4}\\b" val BLOCK_TEXT = "*********"

def identity = "" def op(a1: String, a2: String) = a1 + a2.replaceAll(CREDIT_CARD_REGEX, BLOCK_TEXT).replaceAll(SSN_REGEX, BLOCK_TEXT) + "," }

val monoid = new JsonMonoid val result = json.split(',').foldLeft(monoid.identity)(monoid.op)

Page 12: Monoids

Thanks

Thanks