Slide 1

Slide 1 text

Poor man's type classes revisited @Biacco42

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

At first, what is Type Class

Slide 4

Slide 4 text

What is Type Class Type - litelally Class - a group by reason of common characteris7c Type != Class Type Class == Class of Types Be aware of the seman.cs of the Class and Type here is based on Haskell but Scala

Slide 5

Slide 5 text

What for Type Class For ad hoc polymorphism def sum[A](xs: List[A]): A = ??? // A should be Int / String sum(List("a", "bc", "de")) // => "abcde" sum(List(1, 2, 3)) // => 6 sum(List(true, false)) // Kaboom! Can't compile Polymorphic behavior by instance type def sum[A](xs: List[A]): A = if (xs.isEmpty) A.unit else A.add(xs.head, sum(xs.tail)) Can it be done?

Slide 6

Slide 6 text

In Haskell class MyMonoid a where add :: a -> a -> a instance MyMonoid Int where add x y = x + y instance MyMonoid Double where add x y = x + y mySum :: (MyMonoid a) => a -> a -> a mySum x y = add x y main = do print $ mySum (1::Int) (2::Int) -- 3 print $ mySum (1::Double) (2::Double) -- 3.0 print $ mySum True False -- Kaboom! Can't compile

Slide 7

Slide 7 text

The nature of Type class • Type already defined • Constrain receivable type set by interface • Interface implemented independently the type but associated with the type • Type resolu9on in compile 9me

Slide 8

Slide 8 text

Life without Type Class - 11 Some standard classes for SemiGroup and Monoid abstract class SemiGroup[A] { def add(x: A, y: A): A } abstract class Monoid[A] extends SemiGroup[A] { def unit: A } 1 h$p:/ /lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf

Slide 9

Slide 9 text

Life without Type Class - 21 Two implementa-ons of monoids object stringMonoid extends Monoid[String] { def add(x : String, y : String): String = x.concat(y) def unit : String = "" } object intMonoid extends Monoid[int] { def add(x : Int, y : Int): Int = x + y def unit: Int = 0 } 1 h$p:/ /lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf

Slide 10

Slide 10 text

Life without Type Class - 31 A sum method which works over arbitrary monoids def sum[A](xs : List[A])(m : Monoid[A]): A = if (xs.isEmpty) m.unit else m.add(xs.head, sum(xs.tail)(m)) One invokes this sum method by code such as sum(List("a", "bc", "de"))(stringMonoid) // => "abcde" sum(List(1, 2, 3))(intMonoid) // => 6 sum(List(true, false))(intMonoid) // => Can't compile definitely 1 h$p:/ /lampwww.epfl.ch/~odersky/talks/wg2.8-boston06.pdf

Slide 11

Slide 11 text

Type safe but duplica0on sum(List("a", "bc", "de"))(stringMonoid) // => "abcde" sum(List("a", "bc", "de")) // Want to be

Slide 12

Slide 12 text

Implicits

Slide 13

Slide 13 text

Implicit parameter Implicitly inser.ng value by Type

Slide 14

Slide 14 text

Implicit parameter Implicitly inser.ng value by Type def sum[A](xs : List[A])(implicit m : Monoid[A]): A = if (xs.isEmpty) m.unit else m.add(xs.head, sum(xs.tail)(m)) implicit object stringMonoid extends Monoid[String] { def add(x : String, y : String): String = x.concat(y) def unit : String = "" } implicit object intMonoid extends Monoid[Int] { def add(x : Int, y : Int): Int = x + y def unit: Int = 0 }

Slide 15

Slide 15 text

Implicit parameter Implicitly inser.ng value by Type sum(List(1, 2, 3)) Looks like wanted form! Equals to sum(List(1, 2, 3))(intMonoid)

Slide 16

Slide 16 text

vs. Haskell Haskell <-> Scala type class <-> trait / abstract class instance <-> inplicit object context / type class constraint <-> implicit parameter

Slide 17

Slide 17 text

Haskell code revisited class MyMonoid a where add :: a -> a -> a instance MyMonoid Int where add x y = x + y instance MyMonoid Double where add x y = x + y mySum :: (MyMonoid a) => a -> a -> a mySum x y = add x y main = do print $ mySum (1::Int) (2::Int) -- 3 print $ mySum (1::Double) (2::Double) -- 3.0 print $ mySum True False -- Kaboom! Can't compile

Slide 18

Slide 18 text

Trans Scala code trait MyMonoid[A] { def add(x: A, y: A): A def unit: A } implicit object intMonoid extends MyMonoid[Int] { def add(x : Int, y : Int): Int = x + y def unit: Int = 0 } implicit object doubleMonoid extends MyMonoid[Double] { def add(x : Double, y : Double): Double = x + y def unit: Double = 0 } def mySum[A](x: A, y: A)(implicit m : MyMonoid[A]): A = m.add(x, y) mySum(1, 2) // => 3 mySum(1.0, 2.0) // => 3.0 mysum(true, false) // Compile error

Slide 19

Slide 19 text

Conclusion The beauty of type class and implicit • Type (Interface) with implementa5on at external of the type which is already exists • Sta)c Type Safe • Implicit parameter / defini5on binds to Type / Implement Not for laziness