Poor man's type classes revisited

191e95d4b1db10818fa15181dad4ddd2?s=47 Biacco42
February 26, 2017

Poor man's type classes revisited

Odersky 博士の発表資料 "Poor man's type class" を読んで、Scala における型クラスと implicit について簡単にまとめました

191e95d4b1db10818fa15181dad4ddd2?s=128

Biacco42

February 26, 2017
Tweet

Transcript

  1. 2.
  2. 4.

    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
  3. 5.

    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?
  4. 6.

    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
  5. 7.

    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
  6. 8.

    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
  7. 9.

    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
  8. 10.

    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
  9. 12.
  10. 14.

    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 }
  11. 15.

    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)
  12. 16.

    vs. Haskell Haskell <-> Scala type class <-> trait /

    abstract class instance <-> inplicit object context / type class constraint <-> implicit parameter
  13. 17.

    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
  14. 18.

    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
  15. 19.

    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