Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Functional Algebra: Monoids Applied

Susan Potter
November 10, 2012

Functional Algebra: Monoids Applied

In functional programming, words from Category Theory are thrown around, but how useful are they really?

This session looks at applications of monoids specifically and how using their algebraic properties offers a solid foundation of reasoning in many types of business domains and reduces developer error as computational context complexity increases.

This will provide a tiny peak at Category Theory's practical uses in software development and modeling. Code examples will be in Haskell and Scala, but monoids could be constructed in almost any language by software craftsmen and women utilizing higher orders of reasoning to their code.

Susan Potter

November 10, 2012
Tweet

More Decks by Susan Potter

Other Decks in Programming

Transcript

  1. Monoids: What are they? • An abstraction (laws) not a

    design pattern (forces, context, . . . ) • Algebraic structure . . . over a set with a binary operator and an identity element • Special case category . . . with only one object
  2. Monoids: What are they? • An abstraction (laws) not a

    design pattern (forces, context, . . . ) • Algebraic structure . . . over a set with a binary operator and an identity element • Special case category . . . with only one object
  3. Monoids: What are they? • An abstraction (laws) not a

    design pattern (forces, context, . . . ) • Algebraic structure . . . over a set with a binary operator and an identity element • Special case category . . . with only one object
  4. Monoids: Typeclasses Listing 1: Haskell Monoid Typeclass Definition 1 --

    | In Haskell Prelude Data.Monoid 2 class Monoid a where 3 mempty :: a -- identity 4 mappend :: a -> a -> a -- binary op 5 mconcat :: [a] -> a -- helper Listing 2: Scalaz Monoid Trait Definition 1 // Scalaz 7’s Monoid typeclass definition ,kinda 2 trait Monoid[A] extends Semigroup[A] { self => 3 def zero: A /* identity */ 4 def append(x: A, y: => A): A /* binary op */ 5 } 6 // from SemigroupOps[A] ... 7 final def |+|(other: => A): A = A.append(self, other)
  5. Monoids: Typeclasses Listing 3: Haskell Monoid Typeclass Definition 1 --

    | In Haskell Prelude Data.Monoid 2 class Monoid a where 3 mempty :: a -- identity 4 mappend :: a -> a -> a -- binary op 5 mconcat :: [a] -> a -- helper Listing 4: Scalaz Monoid Trait Definition 1 // Scalaz 7’s Monoid typeclass definition ,kinda 2 trait Monoid[A] extends Semigroup[A] { self => 3 def zero: A /* identity */ 4 def append(x: A, y: => A): A /* binary op */ 5 } 6 // from SemigroupOps[A] ... 7 final def |+|(other: => A): A = A.append(self, other)
  6. Monoids: Typeclasses Listing 5: Haskell Monoid Typeclass Definition 1 --

    | In Haskell Prelude Data.Monoid 2 class Monoid a where 3 mempty :: a -- identity 4 mappend :: a -> a -> a -- binary op 5 mconcat :: [a] -> a -- helper Listing 6: Scalaz Monoid Trait Definition 1 // Scalaz 7’s Monoid typeclass definition ,kinda 2 trait Monoid[A] extends Semigroup[A] { self => 3 def zero: A /* identity */ 4 def append(x: A, y: => A): A /* binary op */ 5 } 6 // from SemigroupOps[A] ... 7 final def |+|(other: => A): A = A.append(self, other)
  7. Monoids: Typeclasses Listing 7: Haskell Monoid Typeclass Definition 1 --

    | In Haskell Prelude Data.Monoid 2 class Monoid a where 3 mempty :: a -- identity 4 mappend :: a -> a -> a -- binary op 5 mconcat :: [a] -> a -- helper Listing 8: Scalaz Monoid Trait Definition 1 // Scalaz 7’s Monoid typeclass definition ,kinda 2 trait Monoid[A] extends Semigroup[A] { self => 3 def zero: A /* identity */ 4 def append(x: A, y: => A): A /* binary op */ 5 } 6 // from SemigroupOps[A] ... 7 final def |+|(other: => A): A = A.append(self, other)
  8. Monoids: Laws • Closure: ∀a, b ∈ S : ab

    ∈ S for all a and b in set S, the result of a and b given to the binary operator is also in set S. • Associativity: ∀a, b, c ∈ S : (ab)c = a(bc) for all a, b, and c in set S, either binary operator can be evaluated first to produce same result. • Identity: ∃e ∈ S : ∀a ∈ S : ea = a = ae there exists an e in set S such that for all a in set S ea evaluates to a and is equal to ae
  9. Monoids: Laws • Closure: ∀a, b ∈ S : ab

    ∈ S for all a and b in set S, the result of a and b given to the binary operator is also in set S. • Associativity: ∀a, b, c ∈ S : (ab)c = a(bc) for all a, b, and c in set S, either binary operator can be evaluated first to produce same result. • Identity: ∃e ∈ S : ∀a ∈ S : ea = a = ae there exists an e in set S such that for all a in set S ea evaluates to a and is equal to ae
  10. Monoids: Laws • Closure: ∀a, b ∈ S : ab

    ∈ S for all a and b in set S, the result of a and b given to the binary operator is also in set S. • Associativity: ∀a, b, c ∈ S : (ab)c = a(bc) for all a, b, and c in set S, either binary operator can be evaluated first to produce same result. • Identity: ∃e ∈ S : ∀a ∈ S : ea = a = ae there exists an e in set S such that for all a in set S ea evaluates to a and is equal to ae
  11. Monoids: Properties (Haskell) 1 -- property based tests for monoid

    "laws" 2 -- does not compile yet; must specify type a 3 module Tests where 4 import Test.QuickCheck (quickCheck) 5 6 -- closure law verified by type system 7 8 propMonoidAssoc :: Monoid a => a -> a -> a -> Bool 9 propMonoidAssoc x y z = 10 mappend (mappend x y) z == mappend x (mappend y z) 11 12 propMonoidIdent :: Monoid a => a -> Bool 13 propMonoidIdent x = 14 mappend mempty x == x && mappend x mempty == x
  12. Monoids: Simple "Natural" Examples Listing 9: Haskell 1 -- OP

    ID List 2 foldr (+) 0 [1,2,3,4] -- 10 3 foldr (*) 1 [1,2,3,4] -- 24 4 foldr (++) [] [[1], [1,2]] -- [1,1,2] 5 foldr (&&) True [True, False, True] -- False 6 foldr (||) False [True, False, True] -- True 7
  13. Monoids: Simple "Natural" Examples Listing 11: Haskell 1 -- OP

    ID List 2 foldr (+) 0 [1,2,3,4] -- 10 3 foldr (*) 1 [1,2,3,4] -- 24 4 foldr (++) [] [[1], [1,2]] -- [1,1,2] 5 foldr (&&) True [True, False, True] -- False 6 foldr (||) False [True, False, True] -- True 7
  14. Monoids: Simple "Natural" Examples Listing 13: Haskell 1 -- OP

    ID List 2 foldr (+) 0 [1,2,3,4] -- 10 3 foldr (*) 1 [1,2,3,4] -- 24 4 foldr (++) [] [[1], [1,2]] -- [1,1,2] 5 foldr (&&) True [True, False, True] -- False 6 foldr (||) False [True, False, True] -- True 7
  15. Monoids: Simple "Natural" Examples Listing 15: Haskell 1 -- OP

    ID List 2 foldr (+) 0 [1,2,3,4] -- 10 3 foldr (*) 1 [1,2,3,4] -- 24 4 foldr (++) [] [[1], [1,2]] -- [1,1,2] 5 foldr (&&) True [True, False, True] -- False 6 foldr (||) False [True, False, True] -- True 7 mconcat = foldr mappend mempty Listing 16: Same in Scala: WTF? 1 List(1,2,3,4).foldRight(0)(_+_) // 10 2 List(1,2,3,4).foldRight(1)(_*_) // 24 3 List(List(1),List(1,2)).foldRight(List[Int]())(_++_) 4 List(true,false,true).foldRight(true)(_&&_) 5 List(true,false,true).foldRight(false)(_||_)
  16. Monoids: Define Your Own (Haskell) Listing 17: Haskell Monoid Definition

    1 import Data.Monoid 2 3 data Asset = Cash Int 4 | Receivables Int ... 5 data Liability = NotesPayable Int 6 | AccountsPayable Int ... 7 -- naive, but illustrative 8 data BalSheet = BalSheet [Asset] [Liability] 9 10 instance Monoid BalSheet where 11 mempty :: m 12 mempty = BalSheet [] [] 13 mappend :: m -> m -> m 14 mappend (BalSheet a1 l1) (BalSheet a2 l2) = 15 BalSheet (mappend a1 a2) (mappend l1 l2)
  17. Monoids: Define Your Own (Scala) Listing 18: Scalaz Monoid Definition

    1 import scalaz._; import Scalaz._; 2 3 // naive, but illustrative 4 case class Portfolio(positions: Seq[Position]) 5 object Portfolio { 6 implicit val portfolioMonoid = 7 new Monoid[Portfolio] { 8 def append(p1: Portfolio , p2: Portfolio) = 9 Portfolio(append(p1.positions , p2.positions)) 10 def zero = Portfolio(Seq.empty) 11 } 12 }
  18. Monoids: So what? • Properties "Interface" Once you understand one

    monoid, you understand them all plus better tests • Type Safe & Type Expressive Can mappend As but not a A and a B where A! = B and myCalc :: Sum a => a -> a • Generic Functions e.g. consolidate = foldr mappend mempty • Highly Applicable Look around your domain. Do you see Monoids Everywhere™ yet?
  19. Monoids: So what? • Properties "Interface" Once you understand one

    monoid, you understand them all plus better tests • Type Safe & Type Expressive Can mappend As but not a A and a B where A! = B and myCalc :: Sum a => a -> a • Generic Functions e.g. consolidate = foldr mappend mempty • Highly Applicable Look around your domain. Do you see Monoids Everywhere™ yet?
  20. Monoids: So what? • Properties "Interface" Once you understand one

    monoid, you understand them all plus better tests • Type Safe & Type Expressive Can mappend As but not a A and a B where A! = B and myCalc :: Sum a => a -> a • Generic Functions e.g. consolidate = foldr mappend mempty • Highly Applicable Look around your domain. Do you see Monoids Everywhere™ yet?
  21. Monoids: So what? • Properties "Interface" Once you understand one

    monoid, you understand them all plus better tests • Type Safe & Type Expressive Can mappend As but not a A and a B where A! = B and myCalc :: Sum a => a -> a • Generic Functions e.g. consolidate = foldr mappend mempty • Highly Applicable Look around your domain. Do you see Monoids Everywhere™ yet?
  22. Monoids: But . . . • Types With Multiple Monoids

    More boilerplate though usually manageable. e.g. Listing 19: Haskell Monoid Typeclass Definition 1 import Data.Monoid (Sum, mconcat) 2 toSums = map Sum 3 mconcat $ toSums [1,2,3,4] • Think! Does it make sense to declare Vector as a Monoid in Haskell?
  23. Monoids: But . . . • Types With Multiple Monoids

    More boilerplate though usually manageable. e.g. Listing 20: Haskell Monoid Typeclass Definition 1 import Data.Monoid (Sum, mconcat) 2 toSums = map Sum 3 mconcat $ toSums [1,2,3,4] • Think! Does it make sense to declare Vector as a Monoid in Haskell?
  24. Automatic Optimal Pipelining http://informatikr.com/2012/redis-pipelining.html 1 jedis.pipelined(new PipelineBlock() { 2 public

    void execute() { 3 incr("hit_count"); 4 get("mbbx6spp:repos_count"); 5 // Do something with values? 6 } 7 }); // Java using Jedis API
  25. Automatic Optimal Pipelining http://informatikr.com/2012/redis-pipelining.html 1 jedis.pipelined(new PipelineBlock() { 2 public

    void execute() { 3 incr("hit_count"); 4 get("mbbx6spp:repos_count"); 5 // Do something with values? 6 } 7 }); // Java using Jedis API 1 -- Haskell using hedis library 2 runRedis conn $ do 3 hits <- incr "hit_count" 4 repos <- get "mbbx6spp:repos_count" 5 -- liftIO $ print (hits, repos)
  26. Monoids: Other Fun Examples • Log Priorities / Filters in

    bittorrent http://jlouisramblings.blogspot.com/2010/02/how-logging-is-performed-in-haskell.html • Associative Alpha Blending http://lukepalmer.wordpress.com/2010/02/05/associative-alpha-blending/ • Tree in Data.Git module of hit package
  27. Monoids: Other Fun Examples • Log Priorities / Filters in

    bittorrent http://jlouisramblings.blogspot.com/2010/02/how-logging-is-performed-in-haskell.html • Associative Alpha Blending http://lukepalmer.wordpress.com/2010/02/05/associative-alpha-blending/ • Tree in Data.Git module of hit package
  28. Monoids: Other Fun Examples • Log Priorities / Filters in

    bittorrent http://jlouisramblings.blogspot.com/2010/02/how-logging-is-performed-in-haskell.html • Associative Alpha Blending http://lukepalmer.wordpress.com/2010/02/05/associative-alpha-blending/ • Tree in Data.Git module of hit package
  29. Bonus: References / Resources • Channel 9 Lectures (Erik Meijer)

    http://channel9.msdn.com/Shows/Going+Deep/ Lecture-Series-Erik-Meijer-Functional-Programming-Fundamentals-Chapter-1 • The Catsters http://www.youtube.com/thecatsters • Haskell Reddit http://www.reddit.com/r/haskell/ • Haskell Cafe http://www.haskell.org/mailman/listinfo/haskell-cafe • Scalaz Mailing List https://groups.google.com/forum/?fromgroups#!forum/scalaz