Last active
January 2, 2016 23:39
-
-
Save manjuraj/8378176 to your computer and use it in GitHub Desktop.
functional typeclasses and object oriented typeclasses
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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