Skip to content

Instantly share code, notes, and snippets.

@cb372
Created April 9, 2016 15:28
Show Gist options
  • Save cb372/235754f3a9e6372101906b3023a6d7db to your computer and use it in GitHub Desktop.
Save cb372/235754f3a9e6372101906b3023a6d7db to your computer and use it in GitHub Desktop.
/*
* Experiment into making ScalaCache generic in the serialization target.
*
* The idea is that different cache implementations can specify different serialization targets.
* Memcached/Redis would have Repr = Array[Byte],
* while in-memory caches (which don't need serialization) would have Repr = NoSerialization.
*
* The serialization target is encoded as a type parameter in `Cache` and `ScalaCache`.
* I tried it using a type member instead, but it turned into a bloodbath
* (you can see the first steps in https://gist.github.com/cb372/b53a0b51974f78212d3e06bdc682e977)
*
* We would provide the following default codecs implicitly:
* - [A, Array[Byte]] for all primitive A (Int, Double, ... )
* - [A <: Serializable, Array[Byte]]
* - [A, NoSerialization] for any A (a dummy codec that will never be used)
*/
object Demo {
sealed trait NoSerialization // the dummy serialization target for in-memory caches
trait Cache[Repr] {
def put[T](value: T)(implicit codec: Codec[T, Repr]): Unit
}
class CaffeineCache extends Cache[NoSerialization] {
def put[T](value: T)(implicit codec: Codec[T, NoSerialization]): Unit = {
println("I don't need to serialize anything")
// put the value in the cache
}
}
class MemcachedCache extends Cache[String] { // this would be Cache[Array[Byte]]
def put[T](t: T)(implicit codec: Codec[T, String]): Unit = {
val serialized = codec.serialize(t)
println(s"Serialized value: $serialized")
// put the value in the cache
}
}
trait ScalaCache[Repr] {
def cache: Cache[Repr]
}
object ScalaCache {
def apply[Repr](c: Cache[Repr]) = new ScalaCache[Repr] {
val cache = c
}
}
trait Codec[A, Repr] {
def serialize(value: A): Repr
}
object Codec {
implicit def anyToNoSerialization[A] = new Codec[A, NoSerialization] {
def serialize(value: A): NoSerialization = ??? // This will never be called
}
implicit val intToString = new Codec[Int, String] {
def serialize(value: Int): String = s"Int as a String: $value"
}
}
// in the scalacache package object
def put[T, Repr](t: T)(implicit scalaCache: ScalaCache[Repr], codec: Codec[T, Repr]): Unit = {
scalaCache.cache.put(t)
}
def main(args: Array[String]) = {
{
implicit val scalaCache = ScalaCache.apply(new MemcachedCache)
put(23) // prints "Serialized value: Int as a String: 23"
}
{
implicit val scalaCache = ScalaCache.apply(new CaffeineCache)
put(23) // prints "I don't need to serialize anything"
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment