diff options
Diffstat (limited to 'playground.scala')
| -rw-r--r-- | playground.scala | 62 |
1 files changed, 53 insertions, 9 deletions
diff --git a/playground.scala b/playground.scala index 290c54c..603ed08 100644 --- a/playground.scala +++ b/playground.scala @@ -1,12 +1,11 @@ - import shapeless.Generic class Playground { - class ScalaStdlibTypes { + class ScalaStdlibTypes { // Motivation class ScalaConcreteTypesWithTypes { - type Rect = (Int, Int) + type Rect = (Int, Int) // this is a Product (AND relation) type Circle = Int - type Shape = Either[Rect, Circle] + type Shape = Either[Rect, Circle] // either implies a Coproduct (OR relation) def area(s: Shape) = s match { case Left((a, b)) => a*b @@ -75,14 +74,59 @@ class Playground { } val employees = List(Employee("a", 1), Employee("b", 2)) println(writeCSV(employees)) - } - val generic_csv_encoder = new GenericCSVEncoder - class ShapelessCSVEncoder { - trait CSVEncoder[A] { - def encode(s: A): List[String] + /** compiler searches for (i.e. resolves )an implicit encoder function matching + * the given type + * + * needs an implicit encoder function in the context for both the types + */ + implicit def pairEncoder[A, B] ( + implicit + aEncoder: CSVEncoder[A], + bEncoder: CSVEncoder[B] + ): CSVEncoder[(A, B)] = + new CSVEncoder[(A, B)] { + def encode(pair: (A, B)): List[String] = { + val (a, b) = pair + aEncoder.encode(a) ++ bEncoder.encode(b) + } + } + implicit val icecreamEncoder: CSVEncoder[IceCream] = { + new CSVEncoder[IceCream] { + def encode(e: IceCream): List[String] = List(e.a, e.b.toString) + } } + case class IceCream(a: String, b: Int) + val icecream = List(IceCream("a", 1), IceCream("b", 2)) + println(writeCSV(employees zip employees)) + + // Standard patterns with companion objects + + trait CsvEncoder2[T] { + def encode(k: T): List[String] + } + /** Demonsrates a standard pattern for generic typeclass companion objects + * + * apply performs implicit compiler resolution, while + * instance wraps a HOF into the encode function defined by the trait + */ + object CsvEncoder2 { + // "Summoner" method + def apply[A](implicit enc: CSVEncoder[A]): CSVEncoder[A] = enc + + // "Constructor" method + def instance[A](func: A => List[String]): CSVEncoder[A] = + new CSVEncoder[A] { + def encode(value: A): List[String] = + func(value) + } + } + // with the new companion object, encode for ice cream can be: + // implicit val icecreamEncoder2: CsvEncoder2[IceCream] = + // instance(x => List(x.a, x.b.toString)) + } + val generic_csv_encoder = new GenericCSVEncoder } object main { |
