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 full-size slide

  2. At first,
    what is Type Class

    View full-size slide

  3. 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 full-size slide

  4. 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 full-size slide

  5. 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 full-size slide

  6. 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 full-size slide

  7. 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 full-size slide

  8. 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 full-size slide

  9. 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 full-size slide

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

    View full-size slide

  11. Implicit parameter
    Implicitly inser.ng value by Type

    View full-size slide

  12. 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 full-size slide

  13. 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 full-size slide

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

    View full-size slide

  15. 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 full-size slide

  16. 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 full-size slide

  17. 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 full-size slide