Introduction to Type Driven Development in Scala Marcus

  • Slides: 64
Download presentation
Introduction to Type Driven Development in Scala Marcus A. Henry, Jr. @dreadedsoftware Software Engineer

Introduction to Type Driven Development in Scala Marcus A. Henry, Jr. @dreadedsoftware Software Engineer @integrichain @dreadedsoftware | @integrichain

def f(a: Int, b: Int): String = { a. to. String + b. to.

def f(a: Int, b: Int): String = { a. to. String + b. to. String } @dreadedsoftware | @integrichain

def f(a: Int, b: Int): String = { a. to. String + b. to.

def f(a: Int, b: Int): String = { a. to. String + b. to. String } @dreadedsoftware | @integrichain

def f(a: Int, b: Int): String = { a. to. String + b. to.

def f(a: Int, b: Int): String = { a. to. String + b. to. String } @dreadedsoftware | @integrichain

def f(a: Int, b: Int): String = { a. to. String + b. to.

def f(a: Int, b: Int): String = { a. to. String + b. to. String } @dreadedsoftware | @integrichain

def f(a: Int, b: Int): String = { a. to. String + b. to.

def f(a: Int, b: Int): String = { a. to. String + b. to. String } @dreadedsoftware | @integrichain

trait My. Trait[A, B]{type Out} object My. Trait{ def apply[A, B, C](): My. Trait[A,

trait My. Trait[A, B]{type Out} object My. Trait{ def apply[A, B, C](): My. Trait[A, B]{type Out = C} = new My. Trait[A, B]{override type Out = C} } @dreadedsoftware | @integrichain

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My.

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My. Trait[A, B]{type Out = C} def apply[A, B, C](): Aux[A, B, C] = new My. Trait[A, B]{override type Out = C} } @dreadedsoftware | @integrichain

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My.

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My. Trait[A, B]{type Out = C} def apply[A, B, C](): Aux[A, B, C] = new My. Trait[A, B]{override type Out = C} } @dreadedsoftware | @integrichain

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My.

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My. Trait[A, B]{type Out = C} def apply[A, B, C](): Aux[A, B, C] = new My. Trait[A, B]{override type Out = C} } @dreadedsoftware | @integrichain

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My.

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My. Trait[A, B]{type Out = C} def apply[A, B, C](): Aux[A, B, C] = new My. Trait[A, B]{override type Out = C} } @dreadedsoftware | @integrichain

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My.

trait My. Trait[A, B]{type Out} object My. Trait{ type Aux[A, B, C] = My. Trait[A, B]{type Out = C} def apply[A, B, C](): Aux[A, B, C] = new My. Trait[A, B]{override type Out = C} } @dreadedsoftware | @integrichain

trait Mapping[A, B]{ def map(a: A): B } @dreadedsoftware | @integrichain

trait Mapping[A, B]{ def map(a: A): B } @dreadedsoftware | @integrichain

val mapping: Mapping[List[Int], List[String]] = new Mapping[List[Int], List[String]]{ override def map(a: List[Int]): List[String] =

val mapping: Mapping[List[Int], List[String]] = new Mapping[List[Int], List[String]]{ override def map(a: List[Int]): List[String] = a. map(_. to. String) } @dreadedsoftware | @integrichain

trait List. Mapping[A, B]{ def map(list: List[A])(f: A => B): List[B] = list. map(f)

trait List. Mapping[A, B]{ def map(list: List[A])(f: A => B): List[B] = list. map(f) } @dreadedsoftware | @integrichain

trait List. Mapping{ def map[A, B](list: List[A])(f: A => B): List[B] = list. map(f)

trait List. Mapping{ def map[A, B](list: List[A])(f: A => B): List[B] = list. map(f) } @dreadedsoftware | @integrichain

object List. Reverse. Mapping extends List. Mapping{ override def map[A, B](list: List[A])(f: A =>

object List. Reverse. Mapping extends List. Mapping{ override def map[A, B](list: List[A])(f: A => B): List[B] = list. reverse. map(f) } @dreadedsoftware | @integrichain

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware |

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware | @integrichain

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware |

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware | @integrichain

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware |

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware | @integrichain

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware |

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware | @integrichain

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware |

trait With. Map[F[_]]{ def map[A, B](m: F[A])(f: A => B): F[B] } @dreadedsoftware | @integrichain

implicit val list. With. Map = new With. Map[List]{ override def map[A, B](m: List[A])(f:

implicit val list. With. Map = new With. Map[List]{ override def map[A, B](m: List[A])(f: A => B): List[B] = m. map(f) } implicit val option. With. Map = new With. Map[Option]{ override def map[A, B](m: Option[A])(f: A => B): Option[B] = m. map(f) } implicit val stream. With. Map = new With. Map[Stream]{ override def map[A, B](m: Stream[A])(f: A => B): Stream[B] = m. map(f) } val reverse. List. With. Map = new With. Map[List]{ override def map[A, B](m: List[A])(f: A => B): List[B] = m. reverse. map(f) } @dreadedsoftware | @integrichain

def pretty. String[ F[_]: With. Map, A](m: F[A])(f: A => String): String = {

def pretty. String[ F[_]: With. Map, A](m: F[A])(f: A => String): String = { implicitly[With. Map[F]]. map(m)(f). to. String } val list = List(rnd, rnd) val stream = Stream(rnd, rnd) val option = Option(rnd) val f 1: Int => String = {i: Int => "As String: " + i. to. String } pretty. String(list)(f 1) pretty. String(option)(f 1) pretty. String(stream)(f 1) @dreadedsoftware | @integrichain

def process. Data[F[_]: With. Map, A, B, C, D](m 1: F[A])( f 1: A

def process. Data[F[_]: With. Map, A, B, C, D](m 1: F[A])( f 1: A => B)( f 2: B => C)( f 3: C => D): F[D] = { val F = implicitly[With. Map[F]] val m 2 = F. map(m 1)(f 1) val m 3 = F. map(m 2)(f 2) F. map(m 3)(f 3) } val f 2: String => Array[Byte] = _. get. Bytes val f 3: Array[Byte] => Long = _. map(_. to. Long). sum process. Data(list)(f 1)(f 2)(f 3) process. Data(option)(f 1)(f 2)(f 3) process. Data(stream)(f 1)(f 2)(f 3) @dreadedsoftware | @integrichain

Some Type Some Function @dreadedsoftware | @integrichain

Some Type Some Function @dreadedsoftware | @integrichain

Some Function Some Typeclass Instance @dreadedsoftware | @integrichain

Some Function Some Typeclass Instance @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/hlists. scala sealed trait HList extends Product with Serializable final case class

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/hlists. scala sealed trait HList extends Product with Serializable final case class : : [+H, override def to. String case _: : : [_, _] => case _ => head+" : : } } +T <: HList](head : H, tail : T) extends HList { = head match { "("+head+") : : "+tail. to. String sealed trait HNil extends HList { def : : [H](h : H) = shapeless. : : (h, this) override def to. String = "HNil" } case object HNil extends HNil @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/hlists. scala sealed trait HList extends Product with Serializable final case class

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/hlists. scala sealed trait HList extends Product with Serializable final case class : : [+H, override def to. String case _: : : [_, _] => case _ => head+" : : } } +T <: HList](head : H, tail : T) extends HList { = head match { "("+head+") : : "+tail. to. String sealed trait HNil extends HList { def : : [H](h : H) = shapeless. : : (h, this) override def to. String = "HNil" } case object HNil extends HNil @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type

https: //github. com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/ops/hlists. scala#L 62 trait Mapped[L <: HList, F[_]] extends Serializable { type Out <: HList } object Mapped { … type Aux[L <: HList, F[_], Out 0 <: HList] = Mapped[L, F] { type Out = Out 0 } implicit def hnil. Mapped[F[_]]: Aux[HNil, F, HNil] = new Mapped[HNil, F] { type Out = HNil } … implicit def hlist. Mapped 1[ H, T <: HList, F[_], Out. M <: HList](implicit mt: Mapped. Aux[T, F, Out. M]): Aux[H : : T, F, F[H] : : Out. M] = new Mapped[H : : T, F] { type Out = F[H] : : Out. M } } @dreadedsoftware | @integrichain

def zipper[A, B, C]( a: List[A], b: List[B], c: List[C] ): List[(A, (B, C))]

def zipper[A, B, C]( a: List[A], b: List[B], c: List[C] ): List[(A, (B, C))] = a. zip(b. zip(c)) @dreadedsoftware | @integrichain

trait Zip[F[_]]{ def apply[A, B](a: F[A], b: F[B]): F[(A, B)] } @dreadedsoftware | @integrichain

trait Zip[F[_]]{ def apply[A, B](a: F[A], b: F[B]): F[(A, B)] } @dreadedsoftware | @integrichain

def zipper[F[_]: Zip, A, B, C]( a: F[A], b: F[B], c: F[C]): F[(A, (B,

def zipper[F[_]: Zip, A, B, C]( a: F[A], b: F[B], c: F[C]): F[(A, (B, C))] = { val F = implicitly[Zip[F]] F(a, F(b, c)) } @dreadedsoftware | @integrichain

def zipper[F[_]: Zip, H, T]( h: F[H], t: F[T]): F[(H, T)] = { val

def zipper[F[_]: Zip, H, T]( h: F[H], t: F[T]): F[(H, T)] = { val F = implicitly[Zip[F]] F(h, t) } @dreadedsoftware | @integrichain

implicit val Zip. List = new Zip[List]{ override def apply[A, B]( a: List[A], b:

implicit val Zip. List = new Zip[List]{ override def apply[A, B]( a: List[A], b: List[B]): List[(A, B)] = a. zip(b) } val with 2 = zipper(list 1, list 2) val with 3 = zipper(list 1, zipper(list 2, list 3)) val with 6 = zipper(list 1, zipper(list 2, zipper(list 3, zipper(list 4, zipper(list 5, list 6))))) @dreadedsoftware | @integrichain

implicit def zipper[F[_]: Zip, H, T](implicit h: F[H], t: F[T]): F[(H, T)] = {

implicit def zipper[F[_]: Zip, H, T](implicit h: F[H], t: F[T]): F[(H, T)] = { val F = implicitly[Zip[F]] F(h, t) } @dreadedsoftware | @integrichain

implicit def zipper[F[_]: Zip, H, T](implicit h: F[H], t: F[T]): F[(H, T)] = {

implicit def zipper[F[_]: Zip, H, T](implicit h: F[H], t: F[T]): F[(H, T)] = { val F = implicitly[Zip[F]] F(h, t) } @dreadedsoftware | @integrichain

implicit def zipper[F[_]: Zip, H, T](implicit h: F[H], t: F[T]): F[(H, T)] = {

implicit def zipper[F[_]: Zip, H, T](implicit h: F[H], t: F[T]): F[(H, T)] = { val F = implicitly[Zip[F]] F(h, t) } @dreadedsoftware | @integrichain

type F[A] = List[A] type Result = F[ (Int, (Long, (String, (Double, (Float, Array[Byte])

type F[A] = List[A] type Result = F[ (Int, (Long, (String, (Double, (Float, Array[Byte]) ))))] implicit implicit val val val list 1: list 2: list 3: list 4: list 5: list 6: List[Int] = ? ? ? List[Long] = ? ? ? List[String] = ? ? ? List[Double] = ? ? ? List[Float] = ? ? ? List[Array[Byte]] = ? ? ? implicitly[Result] @dreadedsoftware | @integrichain

trait Zip. G[F[_], G[_, _]]{ def apply[A, B](a: F[A], b: F[B]): F[G[A, B]] }

trait Zip. G[F[_], G[_, _]]{ def apply[A, B](a: F[A], b: F[B]): F[G[A, B]] } implicit def zipper[F[_], G[_, _], H, T](implicit F: Zip. G[F, G], h: F[H], t: F[T]): F[G[H, T]] = { F(h, t) } implicit val zip. List. Tuple 2 = new Zip. G[List, Tuple 2]{ override def apply[A, B]( a: List[A], b: List[B]): List[(A, B)] = a. zip(b) } @dreadedsoftware | @integrichain

implicit val zip. List. Tuple 2 = new Zip. G[List, override def apply[A, B](

implicit val zip. List. Tuple 2 = new Zip. G[List, override def apply[A, B]( a: List[A], b: List[B]): List[(A, B)] = } implicit val zip. List. Either = new Zip. G[List, override def apply[A, B]( a: List[A], b: List[B]): List[Either[A, for{a <- a; b <- b}yield{ if(a. to. String. size < b. to. String. size) else Right(b) } } @dreadedsoftware | @integrichain Tuple 2]{ a. zip(b) Either]{ B]] = Left(a)

type F[A] = List[A] type Result = F[ (Int, (Long, (String, (Double, (Float, Array[Byte])

type F[A] = List[A] type Result = F[ (Int, (Long, (String, (Double, (Float, Array[Byte]) ))))] implicit implicit val val val list 1: list 2: list 3: list 4: list 5: list 6: List[Int] = ? ? ? List[Long] = ? ? ? List[String] = ? ? ? List[Double] = ? ? ? List[Float] = ? ? ? List[Array[Byte]] = ? ? ? implicitly[Result] @dreadedsoftware | @integrichain

type F[A] = List[A] type Result = F[ Either[Int, Either[Long, Either[String, Either[Double, Either[Float, Array[Byte]]

type F[A] = List[A] type Result = F[ Either[Int, Either[Long, Either[String, Either[Double, Either[Float, Array[Byte]] ]]]]] implicit implicit val val val list 1: list 2: list 3: list 4: list 5: list 6: List[Int] = ? ? ? List[Long] = ? ? ? List[String] = ? ? ? List[Double] = ? ? ? List[Float] = ? ? ? List[Array[Byte]] = ? ? ? implicitly[Result] @dreadedsoftware | @integrichain

def stringify 1[A, B, C]( fa: A => String, fb: B => String, fc:

def stringify 1[A, B, C]( fa: A => String, fb: B => String, fc: C => String, in: List[(A, (B, C))]): String = { in. map{case (a, (b, c)) => fa(a) + ", " + fb(b) + ", " + fc(c) }. mk. String("(", "; ", ")") } @dreadedsoftware | @integrichain

import cats. Functor val functor. List = new Functor[List]{ override def map[A, B](fa: List[A])(f:

import cats. Functor val functor. List = new Functor[List]{ override def map[A, B](fa: List[A])(f: A => B): F[B] = fa. map(f) } def stringify 2[F[_]: Functor, A, B, C]( fa: A => String, fb: B => String, fc: C => String, in: F[(A, (B, C))]): String = { val F = implicitly[Functor[F]] F. map(in){case (a, (b, c)) => fa(a) + ", " + fb(b) + ", " + fc(c) } ? ? ? } @dreadedsoftware | @integrichain

import cats. Show def stringify 3[F[_]: Functor, A, B, C]( fa: A => String,

import cats. Show def stringify 3[F[_]: Functor, A, B, C]( fa: A => String, fb: B => String, fc: C => String, in: F[(A, (B, C))])(implicit FS: Show[F[String]]): String = { val F = implicitly[Functor[F]] val result = F. map(in){case (a, (b, c)) => fa(a) + ", " + fb(b) + ", " + fc(c) } FS. show(result) } @dreadedsoftware | @integrichain

def stringify 4[F[_]: Functor, A: Show, B: Show, C: Show]( in: F[(A, (B, C))])(implicit

def stringify 4[F[_]: Functor, A: Show, B: Show, C: Show]( in: F[(A, (B, C))])(implicit FS: Show[F[String]]): String = { val F = implicitly[Functor[F]] val fa = implicitly[Show[A]]. show _ val fb = implicitly[Show[B]]. show _ val fc = implicitly[Show[C]]. show _ val result = F. map(in){case (a, (b, c)) => fa(a) + ", " + fb(b) + ", " + fc(c) } FS. show(result) } @dreadedsoftware | @integrichain

def stringify 5[F[_]: Functor, A: Show, B: Show]( in: F[(A, B)])(implicit FS: Show[F[String]]): String

def stringify 5[F[_]: Functor, A: Show, B: Show]( in: F[(A, B)])(implicit FS: Show[F[String]]): String = { val F = implicitly[Functor[F]] val fa = implicitly[Show[A]]. show _ val fb = implicitly[Show[B]]. show _ val result = F. map(in){case (a, b) => fa(a) + ", " + fb(b) } FS. show(result) } @dreadedsoftware | @integrichain

implicit def make. Show[A: Show, B: Show]: Show[(A, B)] = { val fa =

implicit def make. Show[A: Show, B: Show]: Show[(A, B)] = { val fa = implicitly[Show[A]]. show _ val fb = implicitly[Show[B]]. show _ new Show[(A, B)]{ override def show(t: (A, B)): String = { val (a, b) = t "(" + fa(a) + ", " + fb(b) + ")“ } } } @dreadedsoftware | @integrichain

def stringify[F[_]: Functor, A: Show]( in: F[A])(implicit FS: Show[F[String]]): String = { val F

def stringify[F[_]: Functor, A: Show]( in: F[A])(implicit FS: Show[F[String]]): String = { val F = implicitly[Functor[F]] val fa = implicitly[Show[A]]. show _ val result = F. map(in)(fa) FS. show(result) } @dreadedsoftware | @integrichain

implicit val Show. List. String = new Show[List[String]]{ def show(in: List[String]): String = in.

implicit val Show. List. String = new Show[List[String]]{ def show(in: List[String]): String = in. mk. String("(", "; ", ")") } implicit val show. Int = new Show[Int]{ override def show(in: Int): String = in. to. String} implicit val show. Long = new Show[Long]{ override def show(in: Long): String = in. to. String} implicit val show. String = new Show[String]{ override def show(in: String): String = in} implicit val show. Double = new Show[Double]{ override def show(in: Double): String = f"$in%. 2 f"} implicit val show. Float = new Show[Float]{ override def show(in: Float): String = f"$in%. 2 f"} implicit val show. Array. Byte = new Show[Array[Byte]]{ override def show(in: Array[Byte]): String = new String(in)} @dreadedsoftware | @integrichain

//Write thing with our writer val result = implicitly[Result 1] //Read the thing back

//Write thing with our writer val result = implicitly[Result 1] //Read the thing back with our reader println(stringify(result)) @dreadedsoftware | @integrichain

Questions? @dreadedsoftware @integrichain @dreadedsoftware | @integrichain

Questions? @dreadedsoftware @integrichain @dreadedsoftware | @integrichain