I don't get the following code to compile and I am curious of what I did wrong.
I defined a Contravariant Jsonwriter Trait and a function accepting implicit writers:
trait JsonWriter[-A] {
def write(value: A): Json
}
object Json {
def toJson[A](value: A)(implicit writer: JsonWriter[A]): Json =
writer.write(value)
}
Additionally I have defined some instances of these writers:
object JsonWriterInstances {
implicit val stringWriter: JsonWriter[String] =
(value: String) => JsString(value)
implicit val doubleWriter: JsonWriter[Double] =
(value: Double) => JsNumber(value)
class OptionWriter[-T](writer: JsonWriter[T]) extends JsonWriter[Option[T]] {
def write(value: Option[T]): Json = {
value match {
case None => JsNull
case Some(x) => writer.write(x)
}
}
}
implicit def optionWriter[T](implicit writer: JsonWriter[T]):
JsonWriter[Option[T]] = new OptionWriter[T](writer)
}
Now I have written a test:
"write double Option" in {
Some(1.0).toJson should be(JsNumber(1.0))
None.toJson should be(JsNull)
}
The first test for Some(1.0) works fine The second one for None throws:
Error:(40, 12) could not find implicit value for parameter writer: JsonWriter[None.type]
None.toJson should be(JsNull)
If you want to try the code my JsonType definitions for this example are:
sealed trait Json
final case class JsObject(get: Map[String, Json]) extends Json
final case class JsString(get: String) extends Json
final case class JsNumber(get: Double) extends Json
case object JsNull extends Json
None
, if you dont say anything else, is a Option[Nothing]
, so OptionWriter[Nothing]
needs a JsonWriter[Nothing]
. If you try Json.toJson(Some(1))
is the same, there is no JsonWriter[Int]
.
On the other hand, Json.toJson(None:Option[String])
works, because OptionWriter[String] can get a JsonWriter[String].