I use the JSON library for the Play platform, which uses a type class to implement the Json.toJson function. (I may decide to use another technique with less static typing, such as reflection, but for now I want to use this library because it helps me learn about the Scala type system.)
I have a bunch of simple case classes that need to be passed to toJson , so I have to implement an implicit Writes[T] object for each of them. The first section may look like this for each of the classes.
// An example class case class Foo(title: String, lines: List[String]) // Make 'Foo' a member of the 'Writes' typeclass implicit object FooWrites extends Writes[Foo] { def writes(f: Foo) : JsValue = { val fields = Seq("title" -> toJson(f.title), "lines" -> toJson(f.lines)) JsObject(fields) } }
Each class will have a similar implicit value, so I could abstract the general part as shown below. But this does not compile because I'm not sure how to declare a type.
def makeSimpleWrites[C](fields: (String, C => T??)*) : Writes[C] = { new Writes[C] { def writes(c: C) : JsValue = { val jsFields = fields map { case (name, get) => (name, toJson(get(c)))} JsObject(jsFields) } } } implicit val fooWrites : Writes[Foo] = makeSimpleWrites[Foo]("title" -> {_.title}, "lines" -> {_.lines}) implicit val otherWrites ...
The problem is the type T , which I want to pass to makeSimpleWrites . It cannot be a parameter of a normal type, because T is different for each element in fields . Is this an existential type? I have not used one of them yet. Syntax interception ...
def makeSimpleWrites[C](fields: (String, C=>T forSome { type T; implicit Writes[T] })*)
Is this possible in Scala? If so, what is the syntax?