aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorJon Pretty <jon.pretty@propensive.com>2017-10-30 12:55:57 +0100
committerJon Pretty <jon.pretty@propensive.com>2017-10-30 12:55:57 +0100
commit8edaa6e2adbb4aa724a7829be5003fdabb01628a (patch)
tree4138ee6e39625d8b65001a678e2cf37b6173b383 /examples
parent8cd72499b92d745ce3e3f2621a03ab61ce78ef85 (diff)
downloadmagnolia-8edaa6e2adbb4aa724a7829be5003fdabb01628a.tar.gz
magnolia-8edaa6e2adbb4aa724a7829be5003fdabb01628a.tar.bz2
magnolia-8edaa6e2adbb4aa724a7829be5003fdabb01628a.zip
Derivation working for Show and Eq
Diffstat (limited to 'examples')
-rw-r--r--examples/src/main/scala/cats.scala19
-rw-r--r--examples/src/main/scala/eq.scala50
-rw-r--r--examples/src/main/scala/typeclasses.scala93
3 files changed, 93 insertions, 69 deletions
diff --git a/examples/src/main/scala/cats.scala b/examples/src/main/scala/cats.scala
deleted file mode 100644
index 2283ce0..0000000
--- a/examples/src/main/scala/cats.scala
+++ /dev/null
@@ -1,19 +0,0 @@
-package magnolia.examples
-
-import scala.collection.immutable.ListMap
-import scala.language.experimental.macros
-
-import cats.Show
-import magnolia.{Coderivation, Macros}
-
-object catsShowDerivation {
-
- val ShowDerivation = new Coderivation[Show] {
- type Return = String
- def call[T](show: Show[T], value: T): String = show.show(value)
- def construct[T](body: T => String): Show[T] = body(_)
- def join(name: String, xs: ListMap[String, String]): String =
- xs.map { case (k, v) => s"$k=$v" }.mkString(s"$name(", ", ", ")")
- }
-
-}
diff --git a/examples/src/main/scala/eq.scala b/examples/src/main/scala/eq.scala
deleted file mode 100644
index 5a4c9fa..0000000
--- a/examples/src/main/scala/eq.scala
+++ /dev/null
@@ -1,50 +0,0 @@
-package magnolia.examples
-
-import magnolia._
-
-import language.experimental.macros
-import collection.immutable.ListMap
-
-object `package` {
- implicit class Equable[T: Eq](t: T) {
- def isEqualTo(other: T): Boolean = implicitly[Eq[T]].isEqual(t, other)
- }
-
- implicit val eqString: Eq[String] = _ == _
- implicit val eqBool: Eq[Boolean] = _ == _
-
- implicit def eqList[T: Eq]: Eq[List[T]] =
- (l1, l2) => l1.size == l2.size && (l1 zip l2).forall { case (e1, e2) => e1 isEqualTo e2 }
-
- implicit def eqSet[T: Eq]: Eq[Set[T]] =
- (s1, s2) => s1.size == s2.size && (s1 zip s2).forall { case (e1, e2) => e1 isEqualTo e2 }
-}
-
-sealed trait Tree
-case class Branch(left: Tree, right: Tree) extends Tree
-case class Leaf(value: Int) extends Tree
-
-sealed trait Entity
-case class Person(name: String, address: Address) extends Entity
-case class Organization(name: String, contacts: Set[Person]) extends Entity
-case class Address(lines: List[String], country: Country)
-case class Country(name: String, code: String, salesTax: Boolean)
-
-trait Eq[T] { def isEqual(a: T, b: T): Boolean }
-
-object Eq {
-
- implicit val eqInt: Eq[Int] = _ == _
-
- val derivation: Coderivation2[Eq] = new Coderivation2[Eq] {
- type Return = Boolean
-
- def call[T](eq: Eq[T], value1: T, value2: T): Boolean =
- if(value1.getClass == value2.getClass) eq.isEqual(value1, value2) else false
-
- def construct[T](body: (T, T) => Boolean): Eq[T] = body(_, _)
- def join(className: String, elements: ListMap[String, Boolean]): Boolean =
- elements.forall(_._2)
- }
-
-}
diff --git a/examples/src/main/scala/typeclasses.scala b/examples/src/main/scala/typeclasses.scala
new file mode 100644
index 0000000..bc5df94
--- /dev/null
+++ b/examples/src/main/scala/typeclasses.scala
@@ -0,0 +1,93 @@
+package magnolia.examples
+
+import scala.collection.immutable.ListMap
+import scala.language.existentials
+import scala.language.higherKinds
+
+import magnolia._
+import scala.reflect._
+import scala.reflect.macros._
+import scala.language.experimental.macros
+import scala.annotation.unchecked.uncheckedVariance
+
+
+object Show {
+ def join[T](construct: Any, className: String, elems: List[Param[Show, T]])(value: T): String =
+ elems.map { call => s"${call.label}=${call.typeclass.show(call.dereference(value))}" }.mkString(s"{", ",", "}")
+
+ def split[T](subclasses: List[Magnolia.Subclass[Show, T]])(value: T): String =
+ subclasses.map { sub => sub.cast.andThen { value =>
+ sub.typeclass.show(sub.cast(value))
+ } }.reduce(_ orElse _)(value)
+
+ implicit val string: Show[String] = identity
+ implicit val int: Show[Int] = new Show[Int] { def show(s: Int): String = s.toString }
+ implicit def generic[T]: Show[T] = macro Magnolia.generic[T]
+}
+
+trait Show[T] { def show(value: T): String }
+
+object Eq {
+ def join[T](construct: Any, className: String, elems: List[Param[Eq, T]])(param1: T, param2: T): Boolean =
+ elems.forall { case call => call.typeclass.equal(call.dereference(param1), call.dereference(param2)) }
+
+ def split[T](subclasses: List[Magnolia.Subclass[Eq, T]])(param1: T, param2: T): Boolean =
+ subclasses.map { case subclass =>
+ subclass.cast.andThen { value => subclass.typeclass.equal(subclass.cast(param1), subclass.cast(param2)) }
+ }.reduce(_ orElse _)(param1)
+
+ implicit val string: Eq[String] = _ == _
+ implicit val int: Eq[Int] = _ == _
+ implicit def generic[T]: Eq[T] = macro Magnolia.generic[T]
+}
+
+trait Eq[T] { def equal(value: T, value2: T): Boolean }
+
+object Default {
+ case class Call[T](label: String, typeclass: Default[T])
+ case class Subclass[T](label: String, typeclass: Default[T], cast: PartialFunction[_ >: T, T])
+
+ def join[T](construct: ((Call[R] => R) forSome { type R }) => T, className: String, elems: List[Call[_]]): T =
+ construct { call: Call[_] => call.typeclass.default }
+
+ def split[T](subclasses: List[Subclass[T]])(param: T): T = subclasses.head.typeclass.default
+
+
+ implicit val string: Default[String] = new Default[String] { def default: String = "" }
+ implicit val int: Default[Int] = new Default[Int] { def default: Int = 0 }
+ implicit def generic[T]: Default[T] = macro Magnolia.generic[T]
+}
+
+trait Default[T] { def default: T }
+
+object Decoder {
+ case class Call[T](label: String, typeclass: Decoder[T], value: String)
+
+ case class Subclass[T](label: String, typeclass: Decoder[T], cast: PartialFunction[_ >: T, T])
+
+ def join[T](construct: ((Call[R] => R) forSome { type R }) => T, className: String, elems: List[Call[_]]): T =
+ construct { call: Call[_] => call.typeclass.decode(call.value) }
+
+ def split[T](subclasses: List[Subclass[T]])(param: String): T =
+ subclasses.map { case Subclass(name, typeclass, cast) =>
+ PartialFunction[String, T] { case _ if decodes(typeclass, param) => typeclass.decode(param) }
+ }.reduce(_ orElse _)(param)
+
+ def decodes[T](tc: Decoder[T], s: String): Boolean = try { decodes(tc, s); true } catch { case e: Exception => false }
+
+ implicit val string: Decoder[String] = new Decoder[String] { def decode(str: String): String = str }
+ implicit val int: Decoder[Int] = new Decoder[Int] { def decode(str: String): Int = str.toInt }
+ implicit def generic[T]: Decoder[T] = macro Magnolia.generic[T]
+}
+
+trait Decoder[T] { def decode(str: String): T }
+
+sealed trait Tree
+case class Leaf(value: String) extends Tree
+case class Branch(left: Tree, right: Tree) extends Tree
+
+sealed trait Entity
+
+case class Company(name: String) extends Entity
+case class Person(name: String, age: Int) extends Entity
+case class Address(line1: String, occupant: Person)