2. Agenda
● What is typeclass?
● Example
● Category Theory
● Example
● Higher Kinded Types
● Example
● Pros/Cons
3. Type Classes
“Typeclasses define a set of functions that can
have different implementations depending on the
type of data they are given” Real World Haskell
“In computer science, a type class is a type
system construct that supports ad-hoc
polymorphism.” Wikipedia
4. Type Classes
In Haskell, typeclass is the language
feature. Every class is a typeclass.
In Scala, typeclass is a pattern.
5. What isn’t Typeclass?
● It’s not only about FP. You can use it in OOP
as well.
● It’s not only about category theory.
14. Serialization Example (typeclass)
object Serializable {
implicit val adSerializable: Serializable[Ad] =
new Serializable[Ad] {
def serialize(ad: Ad) = "serialized ad"
}
implicit val userSerializable: Serializable[User] =
new Serializable[User] {
def serialize(user: User) = "serialized user"
}
}
15. Serialization Example (typeclass)
scala> doSerialize(new Ad(1, "title1"))
res0: String = serialized ad
scala> doSerialize(new User(1, "user1"))
res1: String = serialized user
scala> doSerialize("bla")
<console>:11: error: could not find implicit value for parameter ser:
Serializable[String]
doSerialize("bla")
16. Category Theory
● Branch of mathematics
● Study of concepts(collection of objects)
and arrows(morphism)
● Functional design patterns in
programming
● Categories have properties and laws
● Categories can be types, cats, cars, …
19. Category Theory
● Abstraction is useful but...
● Don’t forget social aspect of
programming
● Check if everybody is comfortable with
these advanced techniques.
29. How to sum
object Addable {
implicit def numericAddable[A](implicit A: Numeric[A]): Addable[A] =
new Addable[A] {
def plus(x: A, y: A): A = A.plus(x, y)
}
implicit val stringAddable: Addable[String] =
new Addable[String] {
def plus(x: String, y: String): String = x + y
}
}
30. How to sum
def sumGeneric[A](l: List[A])(implicit A: Addable[A]): A =
l.reduce(A.plus)
31. How to sum
trait AddableWithZero[A] extends Addable[A] { def zero: A }
object AddableWithZero {
implicit def numericAddableZero[A](implicit A: Numeric[A]): AddableWithZero[A] =
new AddableWithZero[A] {
def plus(x: A, y: A): A = A.plus(x, y)
def zero: A = A.zero
}
implicit val stringAddableZero: AddableWithZero[String] =
new AddableWithZero[String] {
def plus(x: String, y: String): String = x + y
def zero: String = ""
}
}
32. How to sum
def sumGeneric[A](l: List[A])(implicit A: AddableWithZero[A]): A
= l.foldLeft(A.zero)(A.plus)
34. Semigroup
trait Semigroup[A] {
def append(a: A, b: A): A
}
● Simple typeclass
● Law: Associativity
o append(a1, append(a2, a3) == append(append(a1, a2), a3)
35. Monoid
trait Monoid[A] extends Semigroup[A] {
def zero : A
}
● Identity element on top of semigroup
● Laws: Identity law
o zero append a == a
o a append zero == a
36. How to sum with Scalaz
import scalaz.Monoid
def sumGeneric[A](l: List[A])(implicit A: Monoid[A]): A =
l.foldLeft(A.zero)((x, y) => A.append(x, y))
37. Higher Kinded Types
● HKT gives us the ability to
generalize across type constructors
● Reduces code duplication
● parser combinators, DSL,
comprehensions are written using HKT
39. Higher Kinded Types
import scalaz.Monoid
def sumGeneric[A](l: List[A])(implicit A: Monoid[A]): A =
l.foldLeft(A.zero)((x, y) => A.append(x, y))
What if we want to sum over Vector, Tree or Map?
40. Higher Kinded Types
trait Foldable[F[_]] {
def fold[M](fa: F[M])(implicit M: Monoid[M]): M
}
object Foldable {
implicit val listFoldable: Foldable[List] =
new Foldable[List] {
def fold[M](fa: List[M])(implicit M: Monoid[M]): M =
fa.foldLeft(M.zero)((acc, elem) => M.append(acc, elem))
}
}