1 of 19

Monoids

for

Programmers

(Scala flavor)

Vlad Patryshev, 2013

2 of 19

See common pattern?

  • 2+3==5; 0+n==n+0==n
  • 6*7==42; 1*n==n*1==n
  • max(10, 100) == 100; max(Int.MinValue, x) == x
  • "ab"+"cd"=="abcd"; ""+"ef"=="ef"; "gh"+""=="gh"
  • List(1,2)+List(3,4)==List(1,2,3,4); Nil+List(5,6)==List(5,6); List(7,8)++Nil==List(7,8)
  • Set(1,2,3)+Set(2,4)==Set(1,2,3,4); Set.Empty+Set(5,6)==Set(5,6)

3 of 19

You see Monoids!

  • 2+3==5; 0+n==n+0==n
  • 6*7==42; 1*n==n*1==n
  • max(10, 100) == 100; max(Int.MinValue, x) == x
  • "ab"+"cd"=="abcd"; ""+"ef"=="ef"; "gh"+""=="gh"
  • List(1,2)+List(3,4)==List(1,2,3,4); Nil+List(5,6)==List(5,6); List(7,8)++Nil==List(7,8)
  • Set(1,2,3)+Set(2,4)==Set(1,2,3,4); Set.Empty+Set(5,6)==Set(5,6)

4 of 19

Monoid Rules

1) a Op b = c

2) Zero Op a = a Op Zero = a

signatures:

Op: (T, T) => T

Zero: () => T // or rather just T

but wait, there's more!

5 of 19

Monoid Rules - associativity

(a Op b) Op c == a Op (b Op c)

Not everything is associative

5-(3-2) != (5-3)-2

avg(10, avg(30, 50)) != avg(avg(10, 30), 50)

Magma - like monoid, but no associativity and no unit

  • Tuples: (a, (b, c)) is not the same as ((a,b), c)
  • Binary trees:

6 of 19

Monoid Rules - associativity

(a1 Op (a2 Op (a3 Op (a4...))))

aka fold

(Zero /: a) (x Op y)

Can regroup and run in parallel: thanks to associativity!

This is what empowers Map/Reduce

7 of 19

Mappings between Monoids

f: A → B

f(ZeroA) = ZeroB

f(x OpA y) = f(x) OpB f(y)

e.g.

  • log(1)=0; log(a*b)=log(a)+log(b)
  • twice(n)=2*n; twice(0)=0, twice(n+m)=twice(n)+twice(m)
  • length("")=0; length(s1+s2)=length(s1)+length(s2)
  • sum(Nil)=0; sum(list1+list2)=sum(list1)+sum(list2)
  • prod(Nil)=1; prod(list1+list2)=prod(list1)*prod(list2)
  • maxOf(Nil)=Int.MinValue; maxOf(list1+list2)=max(maxOf(list1)),maxOf(list2))

8 of 19

Free Monoid

take any function, f: A → B

this is equivalent to specifying...

f': List[A] → B

where

f'(Nil) = ZeroB

f'(list1 + list2) = f'(list1) OpB f'(list2)

List[A] is a Free Monoid on A

any type

a monoid

9 of 19

Free Monoid - example

Suppose we have...

object WeekDay extends Enumeration {� val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value�}

and a function

WeekDay=>Int = (Mon->1, Tue->1, Wed->1, Thu->1, Fri->1, Sat->0, Sun->0)

If we have a monoid (Int, 0, +), we can automatically extend this mapping to List[WeekDay]->Int

which counts the number of working days.

10 of 19

Reduce

reduce: List[A] A

with properties:

  • reduce(Nil) = ZeroA
  • reduce(list1+list2) = reduce(list1) OpA reduce(list2)

(This defines an algebra over the functor List[_].)

This is exactly what we did on the previous page, reduce.

11 of 19

That's almost it

Monoids are simple, are not they?

Let's throw in more properties...

12 of 19

Commutative Monoids

a Op b == b Op a

e.g.

  • 2+3==3+2
  • max(2.72, 3.14) == max(3.14, 2.72)

but not these:

  • "hello" + "world" != "world" + "hello"
  • List(1,2,3)+List(4,5,6) != List(4,5,6)+List(1,2,3)

13 of 19

Commutative Monoids

How can we create one?

e.g.

"abracadabra" -> "aaaaabbcdrr"

Order does not matter; numbers matter.

Free commutative monoid on A: a collection of possibly duplicates, order does not matter.

It is called Bag[A]

14 of 19

Commutative Monoids

Bag[A]

{

"partridges in a pear tree": 1,

"turtle doves": 2,

"french hens": 3,

"calling birds": 4,

"golden rings": 5

//etc

}

15 of 19

Commutative Monoids

How about sets?!

16 of 19

Commutative Monoids...

How about sets?!

x Op x == x : x is idempotent

Set('a','b','c') + Set('b','c','d') = Set('a','b','c','d')

17 of 19

Commutative Monoids...

How about sets?!

x Op x == x : x is idempotent

Set('a','b','c') + Set('b','c','d') = Set('a','b','c','d')

Finite set is a free commutative monoid where all elements are idempotent (thank you, Shachaf, for the hint)

another example

  • max(x, x) = x
  • min(x, x) = x

18 of 19

The Whole Picture

Bigger Picture

19 of 19

Questions... really?

Thank you!

(and thanks to my friends on livejournal for their critique)