Type Classes



@ppurang
http://github.com/ppurang


PLUG!

http://www.meetup.com/Scala-Berlin-Brandenburg/

Demo on the console


What are type classes?

  • Type classes first appeared in Haskell to support ad-hoc polymorphism.
  • Ad-hoc polymorphism => A function is defined over many types, acting differently for each one.
  • 1989: Philip Wadler & Stephen Blott, How to make ad-hoc polymorphism less ad hoc
  • It is all compile time
  • Retroactive Extension

’Eq’ in Haskell

class Eq a where
  (==) :: a -> a -> Bool
  (/=) :: a -> a -> Bool

instance Eq Integer where 
  x == y =  x `integerEq` y

instance (Eq a) => Eq (Tree a) where 
  leaf a         == Leaf b          =  a == b
  (Branch l1 r1) == (Branch l2 r2)  =  (l1==l2) && (r1==r2)
  _              == _               =  False

Haskell Type Class is a Language Feature

Scala Type Class is a Pattern or Recipe

’Ord’ in Haskell

class  (Eq a) => Ord a  where
  (<), (<=), (>=), (>)  :: a -> a -> Bool
  max, min              :: a -> a -> a

quicksort :: Ord a => [a] -> [a]
quicksort []     = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) xs

A possible Ord in Scala

type BooleanCompare[A] = A => A => Boolean; import Predef.{implicitly => ?}

trait Ord[A] {
  def max : A => A => A ; def min : A => A => A
  def < : BooleanCompare[A]; def > : BooleanCompare[A]; def <= : BooleanCompare[A]; def >= : BooleanCompare[A]
}

implicit object IntOrd extends Ord[Int] {
  def max = a => b => if (a > b) a else b; def min = a => b => if (a > b) b else a
  def < = a => b => a < b; def > = a => b => a > b
  def <= = a => b => a <= b; def >= = a => b => a >= b
}

//implicits
def quickSortDescendingOrder[A](l: List[A])(implicit x: Ord[A]): List[A] = l match {
  case p :: xs => quickSortDescendingOrder(xs filter (y => x.<(p)(y))) ::: 
                  p :: 
                  quickSortDescendingOrder(xs filter (y => x.>=(p)(y)))
  case _ => Nil
}

//context bounds
def quickSortAscendingOrder[A: Ord](l: List[A]): List[A] = l match {
  case p :: xs => quickSortAscendingOrder(xs filter (y => ?[Ord[A]].>=(p)(y))) ::: 
                  p :: 
                  quickSortAscendingOrder(xs filter (y => ?[Ord[A]].<(p)(y)))
  case _ => Nil
}
  • Scala allows us to enhance a type by declaring implicit conversions to a newer wrapper type (Pimp my class pattern)
  • Scala allows us to define type classes and then make them available unintrusively using implicits (Think Defaults)
  • But that default can be overriden if needed by passing another implementation.

Tip of the Iceberg

type Show[A] = A => String

type Read[A] = String => A

etc. etc.

For more on type classes and other functional goodness:


https://github.com/scalaz/scalaz

Thank You


@ppurang


http://github.com/ppurang


Further Reads

https://gist.github.com/2245812

PLUG again!

http://www.meetup.com/Scala-Berlin-Brandenburg/