Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Poor man's type classes revisited

Biacco42
February 26, 2017

Poor man's type classes revisited

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

Biacco42

February 26, 2017
Tweet

More Decks by Biacco42

Other Decks in Programming

Transcript

  1. Poor man's type classes
    revisited
    @Biacco42

    View Slide

  2. View Slide

  3. At first,
    what is Type Class

    View Slide

  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

    View Slide

  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?

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  12. Implicits

    View Slide

  13. Implicit parameter
    Implicitly inser.ng value by Type

    View Slide

  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
    }

    View Slide

  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)

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide