From d20a3824ce7719deb328ffed002288bedc398f77 Mon Sep 17 00:00:00 2001 From: Jon Pretty Date: Fri, 24 Nov 2017 14:26:17 +0000 Subject: Use virtualized `param` if it is available --- examples/shared/src/main/scala/decode.scala | 3 ++- examples/shared/src/main/scala/default.scala | 3 ++- examples/shared/src/main/scala/eq.scala | 3 ++- examples/shared/src/main/scala/package.scala | 8 ++++++++ examples/shared/src/main/scala/show.scala | 22 +++++++++++++++++++--- 5 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 examples/shared/src/main/scala/package.scala (limited to 'examples') diff --git a/examples/shared/src/main/scala/decode.scala b/examples/shared/src/main/scala/decode.scala index 5b083bd..14ab671 100644 --- a/examples/shared/src/main/scala/decode.scala +++ b/examples/shared/src/main/scala/decode.scala @@ -22,9 +22,10 @@ object Decoder { /** type constructor for new instances of the typeclass */ type Typeclass[T] = Decoder[T] + type ParamType[T, P] = Param[Decoder, T] { type PType = P } /** defines how new [[Decoder]]s for case classes should be constructed */ - def combine[T](ctx: CaseClass[Decoder, T]): Decoder[T] = new Decoder[T] { + def combine[T](ctx: CaseClass[Decoder, T, Param[Decoder, T]]): Decoder[T] = new Decoder[T] { def decode(value: String) = { val (name, values) = parse(value) ctx.construct { param => diff --git a/examples/shared/src/main/scala/default.scala b/examples/shared/src/main/scala/default.scala index 4c1b634..aa9dedc 100644 --- a/examples/shared/src/main/scala/default.scala +++ b/examples/shared/src/main/scala/default.scala @@ -10,10 +10,11 @@ trait Default[T] { def default: T } object Default { type Typeclass[T] = Default[T] + type ParamType[T, P] = Param[Default, T] { type PType = P } /** constructs a default for each parameter, using the constructor default (if provided), * otherwise using a typeclass-provided default */ - def combine[T](ctx: CaseClass[Default, T]): Default[T] = new Default[T] { + def combine[T](ctx: CaseClass[Default, T, Param[Default, T]]): Default[T] = new Default[T] { def default = ctx.construct { param => param.default.getOrElse(param.typeclass.default) } diff --git a/examples/shared/src/main/scala/eq.scala b/examples/shared/src/main/scala/eq.scala index 8ee42a4..6f00458 100644 --- a/examples/shared/src/main/scala/eq.scala +++ b/examples/shared/src/main/scala/eq.scala @@ -11,9 +11,10 @@ object Eq { /** type constructor for the equality typeclass */ type Typeclass[T] = Eq[T] + type ParamType[T, P] = Param[Eq, T] { type PType = P } /** defines equality for this case class in terms of equality for all its parameters */ - def combine[T](ctx: CaseClass[Eq, T]): Eq[T] = new Eq[T] { + def combine[T](ctx: CaseClass[Eq, T, Param[Eq, T]]): Eq[T] = new Eq[T] { def equal(value1: T, value2: T) = ctx.parameters.forall { param => param.typeclass.equal(param.dereference(value1), param.dereference(value2)) } diff --git a/examples/shared/src/main/scala/package.scala b/examples/shared/src/main/scala/package.scala new file mode 100644 index 0000000..c196dbc --- /dev/null +++ b/examples/shared/src/main/scala/package.scala @@ -0,0 +1,8 @@ +package magnolia + +package object examples { + implicit class Extensions[T](t: T) { + def show(implicit show: Show[String, T]): String = show.show(t) + def ===[S >: T: Eq](that: S): Boolean = implicitly[Eq[S]].equal(t, that) + } +} diff --git a/examples/shared/src/main/scala/show.scala b/examples/shared/src/main/scala/show.scala index 50b34ee..a2b3c6b 100644 --- a/examples/shared/src/main/scala/show.scala +++ b/examples/shared/src/main/scala/show.scala @@ -9,25 +9,41 @@ import scala.language.experimental.macros * be something other than a string. */ trait Show[Out, T] { def show(value: T): Out } +case class ShowParam[Out, T, P](label: String, typeclass: Show[Out, P], deref: T => P) { + type PType = P + def show: Show[Out, PType] = typeclass + def dereference(t: T): PType = deref(t) +} + +object Dflt { + implicit def any[T]: Dflt[T] = new Dflt[T] { def default: T = null.asInstanceOf[T] } +} + +trait Dflt[T] { def default: T } + trait GenericShow[Out] { /** the type constructor for new [[Show]] instances * * The first parameter is fixed as `String`, and the second parameter varies generically. */ type Typeclass[T] = Show[Out, T] + type ParamType[T, P] = ShowParam[Out, T, P] def join(typeName: String, strings: Seq[String]): Out + def param[T, P](name: String, typeclassParam: Show[Out, P], default: Option[P], deref: T => P)(implicit auto: Dflt[P]) = + ShowParam[Out, T, P](name, typeclassParam, deref) + /** creates a new [[Show]] instance by labelling and joining (with `mkString`) the result of * showing each parameter, and prefixing it with the class name */ - def combine[T](ctx: CaseClass[Typeclass, T]): Show[Out, T] = new Show[Out, T] { + def combine[T](ctx: CaseClass[Typeclass, T, ParamType[T, _]]): Show[Out, T] = new Show[Out, T] { def show(value: T) = if (ctx.isValueClass) { val param = ctx.parameters.head - param.typeclass.show(param.dereference(value)) + param.show.show(param.dereference(value)) } else { val paramStrings = ctx.parameters.map { param => - s"${param.label}=${param.typeclass.show(param.dereference(value))}" + s"${param.label}=${param.show.show(param.dereference(value))}" } join(ctx.typeName.split("\\.").last, paramStrings) -- cgit v1.2.3