From 1ea072197cf8a992b37d7efe0636358a236b9d6d Mon Sep 17 00:00:00 2001 From: Jon Pretty Date: Sun, 11 Jun 2017 21:36:32 +0200 Subject: Appears to be working for both covariant and contravariant typeclasses --- examples/src/main/scala/example.scala | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'examples') diff --git a/examples/src/main/scala/example.scala b/examples/src/main/scala/example.scala index e61f8bd..c719ad8 100644 --- a/examples/src/main/scala/example.scala +++ b/examples/src/main/scala/example.scala @@ -30,10 +30,10 @@ object Extractor extends Extractor_1 { implicit val stringExtractor: Extractor[String] = Extractor(_.str) implicit val doubleExtractor: Extractor[Double] = Extractor(_.str.length.toDouble) - implicit val dereferencer: Dereferencer[Extractor] { type Value = Thing } = new Dereferencer[Extractor] { + implicit val derivation: CovariantDerivation[Extractor] { type Value = Thing } = new CovariantDerivation[Extractor] { type Value = Thing def dereference(value: Thing, param: String): Thing = value.access(param) - def delegate[T](extractor: Extractor[T], value: Thing): T = extractor.extract(value) + def call[T](extractor: Extractor[T], value: Thing): T = extractor.extract(value) def combine[Supertype, Right <: Supertype](left: Extractor[_ <: Supertype], right: Extractor[Right]): Extractor[Supertype] = left.orElse(right) @@ -41,7 +41,6 @@ object Extractor extends Extractor_1 { def extract(source: Thing): T = body(source) } } - } trait Extractor_1 extends Extractor_2 { @@ -49,6 +48,36 @@ trait Extractor_1 extends Extractor_2 { def extract(source: Thing): List[T] = List(implicitly[Extractor[T]].extract(source)) } } + trait Extractor_2 { implicit def generic[T]: Extractor[T] = macro Macros.magnolia[T, Extractor[_]] } + +trait Serializer[T] { + def serialize(src: T): String +} + +object Serializer extends Serializer_1 { + implicit val deriv: ContravariantDerivation[Serializer] { type Return = String } = new ContravariantDerivation[Serializer] { + type Return = String + def call[T](typeclass: Serializer[T], value: T): String = typeclass.serialize(value) + def construct[T](body: T => String): Serializer[T] = new Serializer[T] { + def serialize(value: T): String = body(value) + } + def join(xs: List[String]): String = xs.mkString(", ") + } +} + +trait Serializer_1 extends Serializer_2 { + implicit val intSerializer: Serializer[Int] = { t => "int" } + implicit val strSerializer: Serializer[String] = { t => "string" } + implicit val doubleSerializer: Serializer[Double] = { t => "double" } + implicit def listSerializer[T: Serializer]: Serializer[List[T]] = { ts => + println(ts) + s"List[${ts.map { t => implicitly[Serializer[T]].serialize(t) }.mkString("-")}]" + } +} + +trait Serializer_2 { + implicit def generic[T]: Serializer[T] = macro Macros.magnolia[T, Serializer[_]] +} -- cgit v1.2.3