Will it Blend?
February 2015
@filippovitale
Will it Blend? - ScalaSyd February 2015
value
value
value
Map Set
key value
key value
key value
List
v v v v
List
Immutable Collection Hierarchy
Traversable Seq List
http://docs.scala-lang.org/tutorials/FAQ/collections.html
Immutable Collection Hierarchy
Traversable Seq List
http://docs.scala-lang.org/tutorials/FAQ/collections.html
def ++[B]
(that:Traversable[B])
:Traversable[B]
Blending Lists
List(1, 2, 3) ++ List(4, 5, 6) == ???
Blending Appending Lists
List(1, 2, 3) ++ List(4, 5, 6) == List(1, 2, 3, 4, 5, 6)
http://www.scala-lang.org/api/current/#scala.collection.immutable.List
http://docs.scala-lang.org/overviews/collections/seqs.html
def ++[B](that: Traversable[B]): List[B]
Returns a new list containing the elements from the left hand
operand followed by the elements from the right hand operand.
Set
Immutable Collection Hierarchy
Traversable Seq
Set
List
HashSet
http://docs.scala-lang.org/tutorials/FAQ/collections.html
Blending Sets
Set(1, 2, 3) ++ Set(4, 5, 6) == ???
Blending Adding Sets
Set(1, 2, 3) ++ Set(4, 5, 6) == Set(5, 1, 6, 2, 3, 4)
http://www.scala-lang.org/api/current/#scala.collection.immutable.Set
http://docs.scala-lang.org/overviews/collections/sets.html
def ++[B](that: Traversable[B]): Set[B]
Returns a new set containing the elements from the left hand
operand followed by the elements from the right hand operand.
Blending Adding Sets
Set(1, 2, 3) ++ Set(4, 5, 6) == Set(5, 1, 6, 2, 3, 4)
Set(1, 2) ++ Set(2, 3) == Set(1, 2, 3)
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015
Map
Immutable Collection Hierarchy
Traversable Seq
Set
Map
List
HashSet
HashMap
http://docs.scala-lang.org/tutorials/FAQ/collections.html
Blending Adding Maps
Map() ++ Map("a" -> 1) == Map("a" -> 1)
http://www.scala-lang.org/api/current/#scala.collection.immutable.Map
http://docs.scala-lang.org/overviews/collections/maps.html
def ++[B](that: Traversable[(A, B)]): Map[A, B]
Returns a new map containing the elements from the left hand
operand followed by the elements from the right hand operand.
Blending Adding Maps
Map("a" -> Set(1, 2)) ++ Map("a" -> Set(2, 3)) == ???
http://www.scala-lang.org/api/current/#scala.collection.immutable.Map
http://docs.scala-lang.org/overviews/collections/maps.html
def ++[B](that: Traversable[(A, B)]): Map[A, B]
Returns a new map containing the elements from the left hand
operand followed by the elements from the right hand operand.
Map("a" -> Set(1, 2)) ++ Map("a" -> Set(2, 3)) == ???
1: Map("a" -> Set(1, 2))
2: Map("a" -> Set(1, 2, 3))
3: Map("a" -> Set(2, 3))
4: RuntimeException
5: Compiler Error
What is the result of “blending” those Maps?
Map("a" -> Set(1, 2)) ++ Map("a" -> Set(2, 3)) == ???
1:
2:
3: Map("a" -> Set(2, 3))
4:
5:
What is the result of “blending” those Maps?
Map("a" -> Set(1, 2)) ??? Map("a" -> Set(2, 3))
Map("a" -> Set(1, 2, 3))
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015
Map with values as Set (of Int)
“a” Set(1, 2)
“key b” Set(4, 7, 5)
“key c” Set(9, 4)
“a” Set(2, 3)
“key c” Set(3, 4)
“key d” Set(5, 6)
val ma:
Map[String, Set[Int]]
val mb:
Map[String, Set[Int]]
Map with values as Set (of Int)
“a” Set(1, 2) “a” Set(2, 3)
“a” Set(1, 2) ++ Set(2, 3)
Map with values as Set (of Int)
“a” Set(1, 2) “a” Set(2, 3)
“a” Set(1, 2, 3)
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
for ((k, v) <- mb) {
???
}
}
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
val result = mutable.Map() ++ ma
for ((k, v) <- mb) {
???
}
result.toMap
}
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
???
}
result.toMap
}
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
if (result.contains(k))
result += k -> (result(k) ++ v)
else
result += k -> v
}
result.toMap
}
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
}
(ma /: mb) { case (result,(k, v)) =>
if (result.contains(k))
result + (k -> (result(k) ++ v))
else
result + (k -> v)
}
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
if (result.contains(k))
result += k -> (result(k) ++ v)
else
result += k -> v
}
result.toMap
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
}
(ma /: mb) { case (result,(k, v)) =>
if (result.contains(k))
result + (k -> (result(k) ++ v))
else
result + (k -> v)
}
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
if (result.contains(k))
result += k -> (result(k) ++ v)
else
result += k -> v
}
result.toMap
mb.foldLeft(ma) { ... }
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
}
(ma /: mb) { case (result,(k, v)) =>
if (result.contains(k))
result + (k -> (result(k) ++ v))
else
result + (k -> v)
}
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
if (result.contains(k))
result += k -> (result(k) ++ v)
else
result += k -> v
}
result.toMap
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
}
(ma /: mb) { case (result,(k, v)) =>
if (result.contains(k))
result + (k -> (result(k) ++ v))
else
result + (k -> v)
}
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
if (result.contains(k))
result += k -> (result(k) ++ v)
else
result += k -> v
}
result.toMap
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] = {
(ma /: mb) { case (result,(k, v)) =>
if (result.contains(k))
result + (k -> (result(k) ++ v))
else
result + (k -> v)
}
}
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
}
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
// .map(_ ++ v).getOrElse(v)
//
//
//
}}
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
// .map(_ ++ v).getOrElse(v)
// .some(_ ++ v).none(v)
//
//
}}
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
// .map(_ ++ v).getOrElse(v)
// .some(_ ++ v).none(v)
// .fold(v)(_ ++ v)
//
}}
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
// .map(_ ++ v).getOrElse(v)
// .some(_ ++ v).none(v)
// .fold(v)(_ ++ v)
// .cata(_ ++ v, v)
}}
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
// .map(_ ++ v).getOrElse(v)
// .some(_ ++ v).none(v)
// .fold(v)(_ ++ v)
// .cata(_ ++ v, v)
}}
http://stackoverflow.com/questions/5328007/why-doesnt-option-have-a-fold-method
http://en.wikipedia.org/wiki/Catamorphism
“Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”
(ma /: mb) { case (result,(k, v)) =>
result + (k -> {
result.get(k) match {
case Some(vr) => vr ++ v
case None => v
}
// .map(_ ++ v).getOrElse(v)
// .some(_ ++ v).none(v)
// .fold(v)(_ ++ v)
// .cata(_ ++ v, v)
}}
http://stackoverflow.com/questions/5328007/why-doesnt-option-have-a-fold-method
http://en.wikipedia.org/wiki/Catamorphism
“Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”
(ma /: mb) { case (result, (k, v)) =>
result + (k -> result.get(k).cata(_ ++ v, v))
}
val result = mutable.Map() ++ ma
mb foreach { case (k, v) =>
result += (k -> result.get(k).cata(_ ++ v, v))
}
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015
Will it Blend? - ScalaSyd February 2015
What if we change
Data Structure?
def blend(ma: Map[String, Set[Int]],
mb: Map[String, Set[Int]])
: Map[String, Set[Int]] =
(ma /: mb) { case (result, (k, v)) =>
result + (k -> result.get(k).cata(_ ++ v, v))
}
Map[String, Set[Int]] Map[String, Map[Int, Set[Int]]]
def blend(ma: Map[String, Map[Int, Set[Int]]],
mb: Map[String, Map[Int, Set[Int]]])
: Map[String, Map[Int, Set[Int]]] =
(ma /: mb) { case (result, (k, v)) =>
result + ??? // { ??? => { ??? } }
}
Map[String, Set[Int]] Map[String, Map[Int, Set[Int]]]
trait Blendable[A] {
def blend(ma: A, mb: A): A
}
new Blendable[...] {
def blend(ma: ..., mb: ...): ... = ???
}
trait Blendable[A] {
def blend(ma: A, mb: A): A
}
new Blendable[...] {
def blend(ma: ..., mb: ...): ... = ???
}
x10 Developer
What is the meaning of
“Blending”?
(in my world)
What blended “as expected”?
List using the ++ binary operator
Set using the ++ binary operator
List(1, 2, 3) ++ List(4, 5, 6) == List(1, 2, 3, 4, 5, 6)
Set(1, 2) ++ Set(2, 3) == Set(1, 2, 3)
(List, ++)
(Set, ++)
(1 blend 2) == ???
What about Int?
(List, ++)
(Set, ++)
(Int, +)
(1 blend 2) == 1 + 2 == 3
What about Int?
(List, ++)
(Set, ++)
(Int, +)
(String, +)("ab" blend "cd") == ("ab" + "cd") == "abcd"
String
(List, ++)
(Set, ++)
(Int, +)
(String, +)
(Map[...], Blendable[...].blend)
Blendable[Map[String, Set[Int]]].blend(ma, mb)
Map[String, Set[Int]]
What can
Mathematicians
tell us here?
Warning
Category Theory ahead
☣
What is a Semigroup?
Michael Barr, Charles Wells - Category Theory for Computing Science
Semigroups
“A semigroup is a set S together with an
associative binary operation m: S × S → S”
Closure Property
http://en.wikipedia.org/wiki/Closure_(mathematics)
trait Semigroup[T] {
def op(a: T, b: T): T
}
For all a, b in T, the result of the operation a ⋅ b is also in T:
∀a, b ∈ T : a∙b ∈ T
http://en.wikipedia.org/wiki/Closure_(mathematics)
trait Semigroup[T] {
def op(a: T, b: T): T
}
def op(a: Boolean, b: Boolean): Boolean
def op(a: Int, b: Int): Boolean
✓
✘
Closure Property
Associative Property
http://en.wikipedia.org/wiki/Associative_property
trait Semigroup[T] {
def op(a: T, b: T): T
}
For all a, b, and c in T, the equation (a ⋅ b) ⋅ c = a ⋅ (b ⋅ c) holds:
∀a, b, c ∈ T : (a∙b)∙c = a∙(b∙c)
(a op b) op c
==
a op (b op c)
What is a Semigroup?
Michael Barr, Charles Wells - Category Theory for Computing Science
Semigroups
“A semigroup is a set S together with an
associative binary operation m: S × S → S”
Scalaz and Semigroup
Scalaz and Semigroup
import scalaz.std.set._
Scalaz and Semigroup
implicit def setSemigroup[A]:Semigroup[Set[A]] =
new Semigroup[Set[A]] {
def append(f1: Set[A], f2: => Set[A]) = f1 ++ f2
}
Scalaz and Semigroup
implicit def setSemigroup[A]:Semigroup[Set[A]] =
new Semigroup[Set[A]] {
def append(f1: Set[A], f2: => Set[A]) = f1 ++ f2
}
op
Scalaz and Semigroup
import scalaz.syntax.semigroup._
import scalaz.std.list._
Set(1, 2) |+| Set(2, 3)
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
Scalaz and Semigroup
import scalaz.syntax.semigroup._
import scalaz.std.list._
List(1, 2) |+| List(3, 4)
res0: scala.collection.immutable.List[Int] = List(1, 2, 3, 4)
Scalaz and Semigroup
import scalaz.syntax.semigroup._
import scalaz.std.string._
"a" |+| "b" |+| "c"
res0: String = abc
/**
* A semigroup in type F must satisfy two laws:
*
* - '''closure''': `∀ a, b in F, append(a, b)` is also in `F`.
* - '''associativity''': `∀ a, b, c` in `F`, the equation
* `append(append(a, b), c) = append(a, append(b , c))` holds.
*/
trait SemigroupLaw {
def associative(f1: F, f2: F, f3: F)(implicit F: Equal[F]): Boolean =
F.equal(append(f1, append(f2, f3)), append(append(f1, f2), f3))
}
import scalaz.scalacheck.ScalazProperties._
semigroup.laws[Int].check
+ semigroup.associative: OK, passed 100 tests.
import scalaz.scalacheck.ScalazProperties._
semigroup.laws[String].check
semigroup.laws[Set[Int]].check
semigroup.laws[List[String]].check
semigroup.laws[Map[Int, Int]].check
+ semigroup.associative: OK, passed 100 tests.
+ semigroup.associative: OK, passed 100 tests.
+ semigroup.associative: OK, passed 100 tests.
+ semigroup.associative: OK, passed 100 tests.
import scalaz.scalacheck.ScalazProperties._
semigroup.laws[Map[String, Set[Int]]].check
import scalaz.scalacheck.ScalazProperties._
semigroup.laws[Map[String, Set[Int]]].check
+ semigroup.associative: OK, passed 100 tests.
Map("a" -> Set(1, 2)) |+| Map("a" -> Set(2, 3))
Map("a" -> Set(1, 2)) |+| Map("a" -> Set(2, 3))
res0: ...immutable.Map[...] = Map(a -> Set(1, 2, 3))
Map("a" -> Set(1, 2)) |+| Map("a" -> Set(2, 3))
“Some data structures form interesting semigroups as long as
the types of the elements they contain also form semigroups.”
“adapted” from: Functional Programming in Scala - Part 3 - Chapter 10 Monoids
Map("a" ->
Map("aa" ->
Map("aaa" ->
Map("aaaa" -> List(1, 3),
"aaab" -> List(2, 4))))) |+| Map("a" ->
Map("aa" ->
Map("aaa" ->
Map("aaaa" -> List(5, 7),
"aaab" -> List(6, 8)))))
Map(a->Map(aa->Map(aaa->Map(aaaa->List(1, 3, 5, 7), aaab->List(2, 4, 6, 8)))))
Map("a" -> 1, "b" -> 4) |+| Map("a" -> 2)
Map("a" -> 1, "b" -> 4) |+| Map("a" -> 2)
res0: ...immutable.Map[...] = Map(a -> 3, b -> 4)
1.some |+| 2.some
res0: Option[Int] = Some(3)
1.some |+| none[Int]
res1: Option[Int] = Some(1)
implicit def optionMonoid[A: Semigroup]: ...
def append(f1: Option[A], f2: => Option[A]) = (f1, f2) match {
case (Some(a1), Some(a2)) => Some(Semigroup[A].append(a1, a2))
case (Some(a1), None) => f1
case (None, sa2 @ Some(a2)) => sa2
case (None, None) => None
}
}
Customised Semigroup
case class MeetupOrganiser(name: String, meetup: String, yowCommunityAward: Int)
val jed = MeetupOrganiser("Jed", "scalasyd", 1)
val mark = MeetupOrganiser("Mark", "scalasyd", 0)
val leo = MeetupOrganiser("Leonardo", "clj-syd", 0)
Customised Semigroup
case class MeetupOrganiser(name: String, meetup: String, yowCommunityAward: Int)
implicit val meetupOrganiserSemigroup = new Semigroup[MeetupOrganiser] {
def append(f1: MeetupOrganiser, f2: => MeetupOrganiser): MeetupOrganiser =
if (f1.yowCommunityAward >= f2.yowCommunityAward) f1 else f2
}
Customised Semigroup
implicit val meetupOrganiserArbitrary: Arbitrary[MeetupOrganiser] =
Arbitrary(for {
n <- arbitrary[String]
m <- arbitrary[String]
r <- arbitrary[Int]
} yield MeetupOrganiser(n, m, r))
implicit val meetupOrganiserEqual: Equal[MeetupOrganiser] = Equal.equal(_ == _)
semigroup.laws[MeetupOrganiser].check
+ semigroup.associative: OK, passed 100 tests.
Customised Semigroup
mark |+| leo
res0: MeetupOrganiser = MeetupOrganiser(Mark,scalasyd,0)
mark |+| leo |+| jed
res1: MeetupOrganiser = MeetupOrganiser(Jed,scalasyd,1)
NonEmptyList(mark, leo, jed).suml1
res2: MeetupOrganiser = MeetupOrganiser(Jed,scalasyd,1)
Will it Blend? - ScalaSyd February 2015
Computer programming as an art (1974)
Map[String, Set[Int]]
Will it Blend? - ScalaSyd February 2015
Thanks!
February 2015
@filippovitale
Questions?
February 2015
@filippovitale

More Related Content

DOCX
CLUSTERGRAM
DOCX
imager package in R and examples..
PDF
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
DOCX
Advanced Data Visualization in R- Somes Examples.
DOCX
R-ggplot2 package Examples
PDF
A walk in graph databases v1.0
PPTX
(2015 06-16) Three Approaches to Monads
PDF
Scala collections
CLUSTERGRAM
imager package in R and examples..
Send + More = Money – Let’s mash 2 monads to solve a simple CSP
Advanced Data Visualization in R- Somes Examples.
R-ggplot2 package Examples
A walk in graph databases v1.0
(2015 06-16) Three Approaches to Monads
Scala collections

What's hot (20)

PDF
ScalaMeter 2014
PDF
Introduction to Scala
PDF
PDF
Scala Parallel Collections
PDF
Data import-cheatsheet
PDF
Scala Functional Patterns
PPTX
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
PDF
From java to kotlin beyond alt+shift+cmd+k
PDF
Functional Programming for OO Programmers (part 2)
KEY
RHadoop, R meets Hadoop
PDF
Perm winter school 2014.01.31
PPTX
Seminar psu 20.10.2013
PDF
Algorithm Design and Analysis - Practical File
PPTX
Seminar PSU 10.10.2014 mme
PPTX
Kotlin standard
PDF
Stata cheat sheet analysis
PDF
[1062BPY12001] Data analysis with R / week 2
PDF
Артём Акуляков - F# for Data Analysis
ODP
Collections In Scala
PDF
Spark 4th Meetup Londond - Building a Product with Spark
ScalaMeter 2014
Introduction to Scala
Scala Parallel Collections
Data import-cheatsheet
Scala Functional Patterns
Seminar PSU 09.04.2013 - 10.04.2013 MiFIT, Arbuzov Vyacheslav
From java to kotlin beyond alt+shift+cmd+k
Functional Programming for OO Programmers (part 2)
RHadoop, R meets Hadoop
Perm winter school 2014.01.31
Seminar psu 20.10.2013
Algorithm Design and Analysis - Practical File
Seminar PSU 10.10.2014 mme
Kotlin standard
Stata cheat sheet analysis
[1062BPY12001] Data analysis with R / week 2
Артём Акуляков - F# for Data Analysis
Collections In Scala
Spark 4th Meetup Londond - Building a Product with Spark
Ad

Similar to Will it Blend? - ScalaSyd February 2015 (20)

PDF
Polimorfismo cosa?
PDF
The Essence of the Iterator Pattern (pdf)
PPTX
The Essence of the Iterator Pattern
PDF
Let’s Talk About Ruby
PPT
Grokking Monads in Scala
PDF
How to extend map? Or why we need collections redesign? - Scalar 2017
PPTX
Running Free with the Monads
PDF
Modular Module Systems
PDF
Monadologie
PDF
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
DOCX
Spark_Documentation_Template1
KEY
正規表現のいろは
PDF
Real World Haskell: Lecture 5
PDF
Scala.io
PDF
Go: It's Not Just For Google
PDF
Refactoring to Macros with Clojure
PDF
Scala by Luc Duponcheel
PDF
Generic Functional Programming with Type Classes
PPTX
EX-6-Implement Matrix Multiplication with Hadoop Map Reduce.pptx
PDF
Create a java project that - Draw a circle with three random init.pdf
Polimorfismo cosa?
The Essence of the Iterator Pattern (pdf)
The Essence of the Iterator Pattern
Let’s Talk About Ruby
Grokking Monads in Scala
How to extend map? Or why we need collections redesign? - Scalar 2017
Running Free with the Monads
Modular Module Systems
Monadologie
Apache Spark - Key Value RDD - Transformations | Big Data Hadoop Spark Tutori...
Spark_Documentation_Template1
正規表現のいろは
Real World Haskell: Lecture 5
Scala.io
Go: It's Not Just For Google
Refactoring to Macros with Clojure
Scala by Luc Duponcheel
Generic Functional Programming with Type Classes
EX-6-Implement Matrix Multiplication with Hadoop Map Reduce.pptx
Create a java project that - Draw a circle with three random init.pdf
Ad

Recently uploaded (20)

PPTX
4Seller: The All-in-One Multi-Channel E-Commerce Management Platform for Glob...
PPTX
Computer Software - Technology and Livelihood Education
PPTX
string python Python Strings: Literals, Slicing, Methods, Formatting, and Pra...
PPTX
ROI Analysis for Newspaper Industry with Odoo ERP
DOC
UTEP毕业证学历认证,宾夕法尼亚克拉里恩大学毕业证未毕业
PPTX
DevOpsDays Halifax 2025 - Building 10x Organizations Using Modern Productivit...
PPTX
hospital managemt ,san.dckldnklcdnkdnkdnjadnjdjn
PPTX
R-Studio Crack Free Download 2025 Latest
PDF
Cloud Native Aachen Meetup - Aug 21, 2025
PPTX
MLforCyber_MLDataSetsandFeatures_Presentation.pptx
PPTX
Download Adobe Photoshop Crack 2025 Free
PDF
novaPDF Pro 11.9.482 Crack + License Key [Latest 2025]
PDF
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
PPTX
Presentation by Samna Perveen And Subhan Afzal.pptx
PPTX
DevOpsDays Halifax 2025 - Building 10x Organizations Using Modern Productivit...
PDF
AI-Powered Fuzz Testing: The Future of QA
PPTX
Chapter 1 - Transaction Processing and Mgt.pptx
PDF
E-Commerce Website Development Companyin india
PPTX
ROI from Efficient Content & Campaign Management in the Digital Media Industry
DOCX
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx
4Seller: The All-in-One Multi-Channel E-Commerce Management Platform for Glob...
Computer Software - Technology and Livelihood Education
string python Python Strings: Literals, Slicing, Methods, Formatting, and Pra...
ROI Analysis for Newspaper Industry with Odoo ERP
UTEP毕业证学历认证,宾夕法尼亚克拉里恩大学毕业证未毕业
DevOpsDays Halifax 2025 - Building 10x Organizations Using Modern Productivit...
hospital managemt ,san.dckldnklcdnkdnkdnjadnjdjn
R-Studio Crack Free Download 2025 Latest
Cloud Native Aachen Meetup - Aug 21, 2025
MLforCyber_MLDataSetsandFeatures_Presentation.pptx
Download Adobe Photoshop Crack 2025 Free
novaPDF Pro 11.9.482 Crack + License Key [Latest 2025]
Multiverse AI Review 2025: Access All TOP AI Model-Versions!
Presentation by Samna Perveen And Subhan Afzal.pptx
DevOpsDays Halifax 2025 - Building 10x Organizations Using Modern Productivit...
AI-Powered Fuzz Testing: The Future of QA
Chapter 1 - Transaction Processing and Mgt.pptx
E-Commerce Website Development Companyin india
ROI from Efficient Content & Campaign Management in the Digital Media Industry
Modern SharePoint Intranet Templates That Boost Employee Engagement in 2025.docx

Will it Blend? - ScalaSyd February 2015

  • 1. Will it Blend? February 2015 @filippovitale
  • 3. value value value Map Set key value key value key value List v v v v
  • 5. Immutable Collection Hierarchy Traversable Seq List http://docs.scala-lang.org/tutorials/FAQ/collections.html
  • 6. Immutable Collection Hierarchy Traversable Seq List http://docs.scala-lang.org/tutorials/FAQ/collections.html def ++[B] (that:Traversable[B]) :Traversable[B]
  • 7. Blending Lists List(1, 2, 3) ++ List(4, 5, 6) == ???
  • 8. Blending Appending Lists List(1, 2, 3) ++ List(4, 5, 6) == List(1, 2, 3, 4, 5, 6) http://www.scala-lang.org/api/current/#scala.collection.immutable.List http://docs.scala-lang.org/overviews/collections/seqs.html def ++[B](that: Traversable[B]): List[B] Returns a new list containing the elements from the left hand operand followed by the elements from the right hand operand.
  • 9. Set
  • 10. Immutable Collection Hierarchy Traversable Seq Set List HashSet http://docs.scala-lang.org/tutorials/FAQ/collections.html
  • 11. Blending Sets Set(1, 2, 3) ++ Set(4, 5, 6) == ???
  • 12. Blending Adding Sets Set(1, 2, 3) ++ Set(4, 5, 6) == Set(5, 1, 6, 2, 3, 4) http://www.scala-lang.org/api/current/#scala.collection.immutable.Set http://docs.scala-lang.org/overviews/collections/sets.html def ++[B](that: Traversable[B]): Set[B] Returns a new set containing the elements from the left hand operand followed by the elements from the right hand operand.
  • 13. Blending Adding Sets Set(1, 2, 3) ++ Set(4, 5, 6) == Set(5, 1, 6, 2, 3, 4) Set(1, 2) ++ Set(2, 3) == Set(1, 2, 3)
  • 16. Map
  • 17. Immutable Collection Hierarchy Traversable Seq Set Map List HashSet HashMap http://docs.scala-lang.org/tutorials/FAQ/collections.html
  • 18. Blending Adding Maps Map() ++ Map("a" -> 1) == Map("a" -> 1) http://www.scala-lang.org/api/current/#scala.collection.immutable.Map http://docs.scala-lang.org/overviews/collections/maps.html def ++[B](that: Traversable[(A, B)]): Map[A, B] Returns a new map containing the elements from the left hand operand followed by the elements from the right hand operand.
  • 19. Blending Adding Maps Map("a" -> Set(1, 2)) ++ Map("a" -> Set(2, 3)) == ??? http://www.scala-lang.org/api/current/#scala.collection.immutable.Map http://docs.scala-lang.org/overviews/collections/maps.html def ++[B](that: Traversable[(A, B)]): Map[A, B] Returns a new map containing the elements from the left hand operand followed by the elements from the right hand operand.
  • 20. Map("a" -> Set(1, 2)) ++ Map("a" -> Set(2, 3)) == ??? 1: Map("a" -> Set(1, 2)) 2: Map("a" -> Set(1, 2, 3)) 3: Map("a" -> Set(2, 3)) 4: RuntimeException 5: Compiler Error What is the result of “blending” those Maps?
  • 21. Map("a" -> Set(1, 2)) ++ Map("a" -> Set(2, 3)) == ??? 1: 2: 3: Map("a" -> Set(2, 3)) 4: 5: What is the result of “blending” those Maps?
  • 22. Map("a" -> Set(1, 2)) ??? Map("a" -> Set(2, 3)) Map("a" -> Set(1, 2, 3))
  • 26. Map with values as Set (of Int) “a” Set(1, 2) “key b” Set(4, 7, 5) “key c” Set(9, 4) “a” Set(2, 3) “key c” Set(3, 4) “key d” Set(5, 6) val ma: Map[String, Set[Int]] val mb: Map[String, Set[Int]]
  • 27. Map with values as Set (of Int) “a” Set(1, 2) “a” Set(2, 3) “a” Set(1, 2) ++ Set(2, 3)
  • 28. Map with values as Set (of Int) “a” Set(1, 2) “a” Set(2, 3) “a” Set(1, 2, 3)
  • 29. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { for ((k, v) <- mb) { ??? } }
  • 30. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { val result = mutable.Map() ++ ma for ((k, v) <- mb) { ??? } result.toMap }
  • 31. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { val result = mutable.Map() ++ ma mb foreach { case (k, v) => ??? } result.toMap }
  • 32. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { val result = mutable.Map() ++ ma mb foreach { case (k, v) => if (result.contains(k)) result += k -> (result(k) ++ v) else result += k -> v } result.toMap }
  • 33. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { } (ma /: mb) { case (result,(k, v)) => if (result.contains(k)) result + (k -> (result(k) ++ v)) else result + (k -> v) } val result = mutable.Map() ++ ma mb foreach { case (k, v) => if (result.contains(k)) result += k -> (result(k) ++ v) else result += k -> v } result.toMap
  • 34. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { } (ma /: mb) { case (result,(k, v)) => if (result.contains(k)) result + (k -> (result(k) ++ v)) else result + (k -> v) } val result = mutable.Map() ++ ma mb foreach { case (k, v) => if (result.contains(k)) result += k -> (result(k) ++ v) else result += k -> v } result.toMap mb.foldLeft(ma) { ... }
  • 35. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { } (ma /: mb) { case (result,(k, v)) => if (result.contains(k)) result + (k -> (result(k) ++ v)) else result + (k -> v) } val result = mutable.Map() ++ ma mb foreach { case (k, v) => if (result.contains(k)) result += k -> (result(k) ++ v) else result += k -> v } result.toMap
  • 36. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { } (ma /: mb) { case (result,(k, v)) => if (result.contains(k)) result + (k -> (result(k) ++ v)) else result + (k -> v) } val result = mutable.Map() ++ ma mb foreach { case (k, v) => if (result.contains(k)) result += k -> (result(k) ++ v) else result += k -> v } result.toMap
  • 37. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = { (ma /: mb) { case (result,(k, v)) => if (result.contains(k)) result + (k -> (result(k) ++ v)) else result + (k -> v) } }
  • 38. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } }
  • 39. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } // .map(_ ++ v).getOrElse(v) // // // }}
  • 40. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } // .map(_ ++ v).getOrElse(v) // .some(_ ++ v).none(v) // // }}
  • 41. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } // .map(_ ++ v).getOrElse(v) // .some(_ ++ v).none(v) // .fold(v)(_ ++ v) // }}
  • 42. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } // .map(_ ++ v).getOrElse(v) // .some(_ ++ v).none(v) // .fold(v)(_ ++ v) // .cata(_ ++ v, v) }}
  • 43. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } // .map(_ ++ v).getOrElse(v) // .some(_ ++ v).none(v) // .fold(v)(_ ++ v) // .cata(_ ++ v, v) }} http://stackoverflow.com/questions/5328007/why-doesnt-option-have-a-fold-method http://en.wikipedia.org/wiki/Catamorphism “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”
  • 44. (ma /: mb) { case (result,(k, v)) => result + (k -> { result.get(k) match { case Some(vr) => vr ++ v case None => v } // .map(_ ++ v).getOrElse(v) // .some(_ ++ v).none(v) // .fold(v)(_ ++ v) // .cata(_ ++ v, v) }} http://stackoverflow.com/questions/5328007/why-doesnt-option-have-a-fold-method http://en.wikipedia.org/wiki/Catamorphism “Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire”
  • 45. (ma /: mb) { case (result, (k, v)) => result + (k -> result.get(k).cata(_ ++ v, v)) } val result = mutable.Map() ++ ma mb foreach { case (k, v) => result += (k -> result.get(k).cata(_ ++ v, v)) }
  • 49. What if we change Data Structure?
  • 50. def blend(ma: Map[String, Set[Int]], mb: Map[String, Set[Int]]) : Map[String, Set[Int]] = (ma /: mb) { case (result, (k, v)) => result + (k -> result.get(k).cata(_ ++ v, v)) } Map[String, Set[Int]] Map[String, Map[Int, Set[Int]]]
  • 51. def blend(ma: Map[String, Map[Int, Set[Int]]], mb: Map[String, Map[Int, Set[Int]]]) : Map[String, Map[Int, Set[Int]]] = (ma /: mb) { case (result, (k, v)) => result + ??? // { ??? => { ??? } } } Map[String, Set[Int]] Map[String, Map[Int, Set[Int]]]
  • 52. trait Blendable[A] { def blend(ma: A, mb: A): A } new Blendable[...] { def blend(ma: ..., mb: ...): ... = ??? }
  • 53. trait Blendable[A] { def blend(ma: A, mb: A): A } new Blendable[...] { def blend(ma: ..., mb: ...): ... = ??? } x10 Developer
  • 54. What is the meaning of “Blending”? (in my world)
  • 55. What blended “as expected”? List using the ++ binary operator Set using the ++ binary operator List(1, 2, 3) ++ List(4, 5, 6) == List(1, 2, 3, 4, 5, 6) Set(1, 2) ++ Set(2, 3) == Set(1, 2, 3)
  • 56. (List, ++) (Set, ++) (1 blend 2) == ??? What about Int?
  • 57. (List, ++) (Set, ++) (Int, +) (1 blend 2) == 1 + 2 == 3 What about Int?
  • 58. (List, ++) (Set, ++) (Int, +) (String, +)("ab" blend "cd") == ("ab" + "cd") == "abcd" String
  • 59. (List, ++) (Set, ++) (Int, +) (String, +) (Map[...], Blendable[...].blend) Blendable[Map[String, Set[Int]]].blend(ma, mb) Map[String, Set[Int]]
  • 62. What is a Semigroup? Michael Barr, Charles Wells - Category Theory for Computing Science Semigroups “A semigroup is a set S together with an associative binary operation m: S × S → S”
  • 63. Closure Property http://en.wikipedia.org/wiki/Closure_(mathematics) trait Semigroup[T] { def op(a: T, b: T): T } For all a, b in T, the result of the operation a ⋅ b is also in T: ∀a, b ∈ T : a∙b ∈ T
  • 64. http://en.wikipedia.org/wiki/Closure_(mathematics) trait Semigroup[T] { def op(a: T, b: T): T } def op(a: Boolean, b: Boolean): Boolean def op(a: Int, b: Int): Boolean ✓ ✘ Closure Property
  • 65. Associative Property http://en.wikipedia.org/wiki/Associative_property trait Semigroup[T] { def op(a: T, b: T): T } For all a, b, and c in T, the equation (a ⋅ b) ⋅ c = a ⋅ (b ⋅ c) holds: ∀a, b, c ∈ T : (a∙b)∙c = a∙(b∙c) (a op b) op c == a op (b op c)
  • 66. What is a Semigroup? Michael Barr, Charles Wells - Category Theory for Computing Science Semigroups “A semigroup is a set S together with an associative binary operation m: S × S → S”
  • 68. Scalaz and Semigroup import scalaz.std.set._
  • 69. Scalaz and Semigroup implicit def setSemigroup[A]:Semigroup[Set[A]] = new Semigroup[Set[A]] { def append(f1: Set[A], f2: => Set[A]) = f1 ++ f2 }
  • 70. Scalaz and Semigroup implicit def setSemigroup[A]:Semigroup[Set[A]] = new Semigroup[Set[A]] { def append(f1: Set[A], f2: => Set[A]) = f1 ++ f2 } op
  • 71. Scalaz and Semigroup import scalaz.syntax.semigroup._ import scalaz.std.list._ Set(1, 2) |+| Set(2, 3) res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
  • 72. Scalaz and Semigroup import scalaz.syntax.semigroup._ import scalaz.std.list._ List(1, 2) |+| List(3, 4) res0: scala.collection.immutable.List[Int] = List(1, 2, 3, 4)
  • 73. Scalaz and Semigroup import scalaz.syntax.semigroup._ import scalaz.std.string._ "a" |+| "b" |+| "c" res0: String = abc
  • 74. /** * A semigroup in type F must satisfy two laws: * * - '''closure''': `∀ a, b in F, append(a, b)` is also in `F`. * - '''associativity''': `∀ a, b, c` in `F`, the equation * `append(append(a, b), c) = append(a, append(b , c))` holds. */ trait SemigroupLaw { def associative(f1: F, f2: F, f3: F)(implicit F: Equal[F]): Boolean = F.equal(append(f1, append(f2, f3)), append(append(f1, f2), f3)) }
  • 76. import scalaz.scalacheck.ScalazProperties._ semigroup.laws[String].check semigroup.laws[Set[Int]].check semigroup.laws[List[String]].check semigroup.laws[Map[Int, Int]].check + semigroup.associative: OK, passed 100 tests. + semigroup.associative: OK, passed 100 tests. + semigroup.associative: OK, passed 100 tests. + semigroup.associative: OK, passed 100 tests.
  • 79. Map("a" -> Set(1, 2)) |+| Map("a" -> Set(2, 3))
  • 80. Map("a" -> Set(1, 2)) |+| Map("a" -> Set(2, 3)) res0: ...immutable.Map[...] = Map(a -> Set(1, 2, 3))
  • 81. Map("a" -> Set(1, 2)) |+| Map("a" -> Set(2, 3)) “Some data structures form interesting semigroups as long as the types of the elements they contain also form semigroups.” “adapted” from: Functional Programming in Scala - Part 3 - Chapter 10 Monoids
  • 82. Map("a" -> Map("aa" -> Map("aaa" -> Map("aaaa" -> List(1, 3), "aaab" -> List(2, 4))))) |+| Map("a" -> Map("aa" -> Map("aaa" -> Map("aaaa" -> List(5, 7), "aaab" -> List(6, 8))))) Map(a->Map(aa->Map(aaa->Map(aaaa->List(1, 3, 5, 7), aaab->List(2, 4, 6, 8)))))
  • 83. Map("a" -> 1, "b" -> 4) |+| Map("a" -> 2)
  • 84. Map("a" -> 1, "b" -> 4) |+| Map("a" -> 2) res0: ...immutable.Map[...] = Map(a -> 3, b -> 4)
  • 85. 1.some |+| 2.some res0: Option[Int] = Some(3) 1.some |+| none[Int] res1: Option[Int] = Some(1)
  • 86. implicit def optionMonoid[A: Semigroup]: ... def append(f1: Option[A], f2: => Option[A]) = (f1, f2) match { case (Some(a1), Some(a2)) => Some(Semigroup[A].append(a1, a2)) case (Some(a1), None) => f1 case (None, sa2 @ Some(a2)) => sa2 case (None, None) => None } }
  • 87. Customised Semigroup case class MeetupOrganiser(name: String, meetup: String, yowCommunityAward: Int) val jed = MeetupOrganiser("Jed", "scalasyd", 1) val mark = MeetupOrganiser("Mark", "scalasyd", 0) val leo = MeetupOrganiser("Leonardo", "clj-syd", 0)
  • 88. Customised Semigroup case class MeetupOrganiser(name: String, meetup: String, yowCommunityAward: Int) implicit val meetupOrganiserSemigroup = new Semigroup[MeetupOrganiser] { def append(f1: MeetupOrganiser, f2: => MeetupOrganiser): MeetupOrganiser = if (f1.yowCommunityAward >= f2.yowCommunityAward) f1 else f2 }
  • 89. Customised Semigroup implicit val meetupOrganiserArbitrary: Arbitrary[MeetupOrganiser] = Arbitrary(for { n <- arbitrary[String] m <- arbitrary[String] r <- arbitrary[Int] } yield MeetupOrganiser(n, m, r)) implicit val meetupOrganiserEqual: Equal[MeetupOrganiser] = Equal.equal(_ == _) semigroup.laws[MeetupOrganiser].check + semigroup.associative: OK, passed 100 tests.
  • 90. Customised Semigroup mark |+| leo res0: MeetupOrganiser = MeetupOrganiser(Mark,scalasyd,0) mark |+| leo |+| jed res1: MeetupOrganiser = MeetupOrganiser(Jed,scalasyd,1) NonEmptyList(mark, leo, jed).suml1 res2: MeetupOrganiser = MeetupOrganiser(Jed,scalasyd,1)
  • 92. Computer programming as an art (1974)