type classes 101 - classification beyond inheritance
TRANSCRIPT
![Page 1: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/1.jpg)
Type classes 101Classification beyond inheritance
Alexey Raga
![Page 2: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/2.jpg)
String
Int
List[Boolean]
case class Name(value: String)
case class Age(value: Int)
case class Person(name: Name, age: Age)
case class Gang(leader: Person, members: List[Person])
Types classify data
![Page 3: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/3.jpg)
String
Int
List[Boolean]
case class Name(value: String)
case class Age(value: Int)
case class Person(name: Name, age: Age)
case class Gang(leader: Person, members: List[Person])
Types classify data
![Page 4: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/4.jpg)
public class Person implements ISerialisable{ public String name; public String address;
...}
public void saveToDisk(ISerialisable obj) { … }
Types classify data
![Page 5: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/5.jpg)
Types classify data
public class Person implements ISerialisable, IJsonSerialisable, IXmlSerialisable, IPrettyPrint{ public String name; public String address;
...}
![Page 6: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/6.jpg)
Expression problem
trait Exprcase class Lit(value: Int) extends Exprcase class Add(x: Expr, y: Expr) extends Expr
val expr = Add(Lit(15), Lit(6))
![Page 7: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/7.jpg)
Expression problem
● Operation extensionadd new operations: eval, prettyPrint, etc.
● Data extensionadd new expressions: Mul, Pow, Neg, ec.
● Static type safetyno isInstanceOf / asInstanceOf
![Page 8: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/8.jpg)
Expression problem
● Operation extensionadd new operations: eval, prettyPrint, etc.
● Data extensionadd new expressions: Mul, Pow, Neg, ec.
● Static type safetyno isInstanceOf / asInstanceOf
![Page 9: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/9.jpg)
Expression problem
trait Expr { def eval: Int def print: String}
case class Lit(value: Int) extends Expr { def eval = ??? def print = ???}
case class Add(x: Expr, y: Expr) extends Expr { def eval = ??? def print = ???}
![Page 10: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/10.jpg)
Expression problem
trait Expr { def eval: Int = this match { case Lit => ??? case Add => ??? } def print: String = this match { case Lit => ??? case Add => ??? }}
case class Lit(value: Int) extends Exprcase class Add(x: Expr, y: Expr) extends Expr
![Page 11: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/11.jpg)
We can do better
![Page 12: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/12.jpg)
Classification
Plants Animals
?
![Page 13: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/13.jpg)
Classification
Fungi
![Page 14: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/14.jpg)
Classification
![Page 15: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/15.jpg)
Classification
![Page 16: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/16.jpg)
Classification
![Page 17: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/17.jpg)
Classifying types
trait Serialisable[A] { def serialise(obj: A) : Array[Byte]}
object PersonSerialisable extends Serialisable[Person] { def serialise(obj: Person): Array[Byte] = ???}
def saveToDisk[A](obj: A, ser: Serialisable[A]) = { val data = ser.serialise(obj) ???}
saveToDisk(Person("john", 99), PersonSerialisable)
![Page 18: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/18.jpg)
Type classes classify types
trait Serialisable[A] { def serialise(obj: A) : Array[Byte]}
implicit object PersonSerialisable extends Serialisable[Person] { def serialise(obj: Person): Array[Byte] = ???}
def saveToDisk[A](obj: A)(implicit ser: Serialisable[A]) = { val data = ser.serialise(obj) ???}
saveToDisk(Person("john", 99))
![Page 19: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/19.jpg)
Type classes classify types
// already defined in Scala// def implicitly[T](implicit e: T) = e
def saveToDisk[A: Serialisable](obj: A) = { val ser = implicitly[Serialisable[A]] val data = ser.serialise(obj) ...}
saveToDisk(Person("john", 99))
![Page 20: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/20.jpg)
Testimony ;)
![Page 21: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/21.jpg)
![Page 22: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/22.jpg)
![Page 23: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/23.jpg)
Just saying...import serialisation.json._//import serialisation.csv._//import serialisation.xml._
def saveToDisk[A](obj: A)(implicit ser: Serialisable[A]) = { val data = ser.serialise(obj) ???}
saveToDisk(Person("john", 99))
![Page 24: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/24.jpg)
Type classes in Scalatrait Ordering[T] { def compare(x : T, y : T) : Int def lteq(x : T, y : T) : Boolean = compare(x, y) <= 0 def gteq(x : T, y : T) : Boolean = compare(x, y) => 0 ...}
trait Numeric[T] extends Ordering[T] { def plus(x : T, y : T) : T def minus(x : T, y : T) : T def negate(x : T) : T ...}
![Page 25: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/25.jpg)
Type classes in Scalatrait Ordering[T] { def compare(x : T, y : T) : Int def lteq(x : T, y : T) : Boolean = compare(x, y) <= 0 def gteq(x : T, y : T) : Boolean = compare(x, y) => 0}
trait Numeric[T] extends Ordering[T] { def plus(x : T, y : T) : T def minus(x : T, y : T) : T def negate(x : T) : T}
trait TraversableOnce[+A] { def sum[B >: A](implicit num : scala.Numeric[B]) : B = ??? def min[B >: A](implicit cmp : scala.Ordering[B]) : A = ??? def max[B >: A](implicit cmp : scala.Ordering[B]) : A = ???}
![Page 26: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/26.jpg)
Type classes in Scalatrait Ordering[T] { def compare(x : T, y : T) : Int def lteq(x : T, y : T) : Boolean = compare(x, y) <= 0 def gteq(x : T, y : T) : Boolean = compare(x, y) => 0}
trait Numeric[T] extends Ordering[T] { def plus(x : T, y : T) : T def minus(x : T, y : T) : T def negate(x : T) : T}
trait TraversableOnce[+A] { def sum[B >: A](implicit num : scala.Numeric[B]) : B = ??? def min[B >: A](implicit cmp : scala.Ordering[B]) : A = ??? def max[B >: A](implicit cmp : scala.Ordering[B]) : A = ???}
val sum = List(1,2,3).sumval min = List(1,2,3).min
![Page 27: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/27.jpg)
Type classes in Scalaztrait Equal[A] { def equal(a1 : A, a2 : A) : Boolean}
trait Show[A] { def shows(a : A) : String}
trait Functor[F[_]] { def map[A, B](fa: F[A])(f: A => B): F[B]}
trait Semigroup[A] { def append(a1 : A, a2 : => A) : A}
trait Monoid[A] extends Semigroup[A] { def zero : A}
![Page 28: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/28.jpg)
Deriving proofs
//tuple of Equals is also an Equalimplicit def tuple2Equal[A: Equal, B: Equal]: Equal[(A, B)] = new Equal[(A, B)] { def equal(a1: (A, B), a2: (A, B)) : Boolean = a1._1 === a2._1 && a1._2 === a2._2 }
//tuple of Semigroups is also a Semigroupimplicit def tuple2Semigroup[A: Semigroup, B: Semigroup]: Semigroup[(A, B)] = { new Semigroup[(A, B)] { def append(p1: (A, B), p2: => (A, B)) = ((p1._1 |+| p2._1), (p1._2 |+| p2._2)) }}
![Page 29: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/29.jpg)
![Page 30: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/30.jpg)
Expression problempackage ep
trait Exprcase class Lit(value: Int) extends Exprcase class Add[A <: Expr, B <: Expr](x: A, y: B) extends Expr
![Page 31: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/31.jpg)
Expression problem
● Operation extensionadd new operations: eval, prettyPrint, etc.
● Data extensionadd new expressions: Mul, Pow, Neg, ec.
● Static type safetyno isInstanceOf / asInstanceOf
![Page 32: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/32.jpg)
Expression problempackage ep.evaluateimport ep._
trait Eval[A <: Expr] { def eval(expr: A) : Int}
object Eval { def evaluate[A <: Expr](expr: A)(implicit evA: Eval[A]) = evA.eval(expr)
implicit object LitEval extends Eval[Lit] { def eval(expr: Lit) = expr.value }
implicit def addEval[A <: Expr, B <: Expr](implicit evA: Eval[A], evB: Eval[B]) = { new Eval[Add[A, B]] { def eval(expr: Add[A, B]) = evA.eval(expr.x) + evB.eval(expr.y) } }}
![Page 33: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/33.jpg)
Expression problempackage ep import evaluate._
Eval.evaluate( Add(Lit(15), Lit(6)) ) === 21
![Page 34: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/34.jpg)
Expression problempackage ep.expressionsimport ep._import evaluate._
case class Mul[A <: Expr, B <: Expr](x: A, y: B) extends Expr
object Mul {
implicit def mulEval[A <: Expr, B <: Expr](implicit evA: Eval[A], evB: Eval[B]) = { new Eval[Mul[A, B]] { def eval(expr: Mul[A, B]) = evA.eval(expr.x) * evB.eval(expr.y) } }
}
![Page 35: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/35.jpg)
Expression problemimport evaluate._import expressions._
Eval.evaluate( Mul(Lit(2), Add(Lit(15), Lit(6))) ) === 42
![Page 36: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/36.jpg)
Expression problempackage ep.operationsimport ep._import ep.expressions._
trait PPrint[A <: Expr] { def print(expr: A) : String}
object PPrint { def prettyPrint[A <: Expr](expr: A)(implicit pa: PPrint[A]) = pa.print(expr)
implicit object LitPrint extends PPrint[Lit] { def print(expr: Lit) = expr.value.toString }
implicit def mulPrint[A <: Expr, B <: Expr](implicit pA: PPrint[A], pB: PPrint[B]) = { new PPrint[Mul[A, B]] { def print(expr: Mul[A, B]) = pA.print(expr.x) + " * " + pB.print(expr.y) } }
![Page 37: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/37.jpg)
Expression problemimport expressions._import operations._import evaluate._
PPrint.prettyPrint( Mul(Lit(2), Add(Lit(15), Lit(6))) ) === "2 * (15 + 6) = 42"
![Page 38: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/38.jpg)
Expression problem
● Operation extensionadd new operations: eval, prettyPrint, etc.
● Data extensionadd new expressions: Mul, Pow, Neg, ec.
● Static type safetyno isInstanceOf / asInstanceOf
![Page 39: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/39.jpg)
● Add behaviours retroactivelyNo need to change existing data types
● Solution to the Expression problemOperation and data extension with static type safety
● Different kinds of operations“instance” (A => String), “factory” (String => A), etc.
![Page 40: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/40.jpg)
![Page 41: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/41.jpg)
![Page 42: Type classes 101 - classification beyond inheritance](https://reader034.vdocuments.mx/reader034/viewer/2022042820/55d06385bb61eb051d8b45ad/html5/thumbnails/42.jpg)
What about us?
Isn't it enough?
No we're not in paradise
This is who we are
This is what we've got
No it's not our paradise