aboutsummaryrefslogtreecommitdiff
path: root/examples/src/main/scala/example.scala
blob: c649fba74b2d2c76ee82bbcd920cdd7d854153eb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package magnolia.examples

import magnolia._

import language.experimental.macros
import language.higherKinds
import collection.immutable.ListMap

object `package` {
  implicit class Showable[T: Show](t: T) {
    def show: String = implicitly[Show[T]].show(t)
  }
  implicit val showString: Show[String] = identity
  implicit val showBool: Show[Boolean] = _.toString
  implicit def showList[T: Show]: Show[List[T]] = xs => xs.map { x => s"list:${implicitly[Show[T]].show(x)}" }.mkString(";")
  implicit def showSet[T: Show]: Show[Set[T]] = s => "set"

  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 EmptyType

sealed trait Tree
case class Branch(left: Tree, right: Tree) extends Tree
case class Leaf(value: Int, no: String) 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 Show[T] { def show(t: T): String }
object Show extends Show_1 {
  implicit val showInt: Show[Int] = _.toString
  implicit val derivation = new ContravariantDerivation[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(xs: ListMap[String, String]): String = xs.map { case (k, v) => s"$k=$v" }.mkString("{", ", ", "}")
  }
}

trait Show_1 {
  implicit def generic[T]: Show[T] = macro Macros.magnolia[T, Show[_]]
}

trait Eq[T] { def isEqual(a: T, b: T): Boolean }

object Eq extends Eq_1 {

  implicit val eqInt: Eq[Int] = _ == _

  implicit val derivation = new ContravariantDerivation2[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(elements: ListMap[String, Boolean]): Boolean = elements.forall(_._2)
  }
}

trait Eq_1 {
  implicit def generic[T]: Eq[T] = macro Macros.magnolia[T, Eq[_]]
}