Skip to content

Instantly share code, notes, and snippets.

@manjuraj
Last active January 2, 2016 23:39
Show Gist options
  • Save manjuraj/8378176 to your computer and use it in GitHub Desktop.
Save manjuraj/8378176 to your computer and use it in GitHub Desktop.
functional typeclasses and object oriented typeclasses
// functional typeclass pattern
// using type traits and implicit parameters
case class Person(name: String, age: Int)
case class Restaurant(name: String, location: String)
// Typeclass
trait Serializable[T] {
def ser(t: T): String
}
// Companion to Typeclass that contains default implementation of typeclasses
// for various types
object Serializable {
@inline def apply[T](implicit ev: Serializable[T]) = ev
implicit object PersonIsSerializable extends Serializable[Person] {
override def ser(p: Person) = p.toString
}
implicit object RestaurantIsSerializable extends Serializable[Restaurant] {
override def ser(r: Restaurant) = r.toString
}
implicit def listToSerializable[T] = new Serializable[List[T]] {
override def ser(l: List[T]) = l.mkString(", ")
}
implicit def tuple2ToSerializable[T, U](implicit t: Serializable[T], u: Serializable[U]) = new Serializable[(T, U)] {
override def ser(tuple: (T, U)) = "(" + t.ser(tuple._1) + ", " + u.ser(tuple._2) + ")"
}
}
// A method with implicit parameter (or context bound) where typeclass is used
def serialize[T](t: T)(implicit ev: Serializable[T]): String = ev.ser(t)
// or, context bound syntax
// def serialize[T : Serializable](t: T): String = implicitly[Serializable[T]].ser(t)
serialize(Person("manju", 31)) // Person(manju,31)
serialize(Restaurant("bar tartine", "san francisco")) // Restaurant(bar tartine,san francisco)
serialize(List(1,2,3)) // 1, 2, 3
// object-oriented typeclass pattern
// using type traits, implicit parameters and implicit conversion
implicit def addSerialize[T](t: T)(implicit ev: Serializable[T]) = new { def serialize = ev.ser(t) }
// Or,
// implicit class SerializableOps[T](val t: T) extends AnyVal {
// def serialize(implicit ev: Serializable[T]) = ev.ser(t)
// }
// Or,
// implicit class SerializableOps[T : Serializable](t: T) {
// def serialize = implicitly[Serializable[T]].ser(t)
// }
Person("manju", 31).serialize // Person(manju,31)
(Person("manju", 31), List(1,2,3)).serialize // (Person(manju,31), 1, 2, 3)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment