Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Recursive implicit proofs with Shapeless HLists

252 views

Published on

Basic introduction to shapeless HLists,
constructing implicit proofs with them and extending those proofs onto generic product-like types with shapeless.Generic

Code: https://github.com/vpavkin/recursive-implicit-proofs-talk

Published in: Software
  • Be the first to comment

  • Be the first to like this

Recursive implicit proofs with Shapeless HLists

  1. 1. 1. 2. 3. 4. 5. 6. 7. 8.
  2. 2. https://github.com/vpavkin/ recursive-implicit-proofs-talk
  3. 3. Ordering[A] implicit val intOrdering = new Ordering[Int] {…}
  4. 4. def sortBy[B](f: A => B) (implicit ord: Ordering[B]) //or def sortBy[B: Ordering](f: A => B) implicit val intOrdering = … implicit def optOrdering[T:Ordering] = new Ordering[Option[T]] { … } // Ok implicitly[Ordering[Option[Int]]] // Can’t prove implicitly[Ordering[Option[String]]]
  5. 5. // type A = Int implicit val intOrdering: Ordering[Int] = …
  6. 6. // type B = Option[A] implicit def optOrdering[A] (implicit ev: Ordering[A]): Ordering[Option[A]] = …
  7. 7. // type C = (A, B) implicit def tuple2Ordering[A, B] (implicit A: Ordering[A], B: Ordering[B]): Ordering[(A, B)] = … implicit def contravariantOrdering[A, B] (implicit C: Converts[A, B], O: Ordering[B]): Ordering[A] =
  8. 8. implicit def ordered[C <% Comparable[C]]: Ordering[C] = … implicit def comparatorToOrdering[C] (implicit cmp: Comparator[C]): Ordering[C] = … A => C + B => C Avoid ambiguous implicits!
  9. 9. You can’t ask for an absence of implicit
  10. 10. 1 -> Container(Option(Container("a"))) (Int, Container[Option[Container[String]]]) String Container[String] Option[Container[String]] Container[Option[Container[String]]] (Int, Container[Option[Container[String]]]) A A => B Ord[T] => Ord[Container[T]] A => B Ord[T] => Ord[Option[T]] A => B Ord[T] => Ord[Container[T]] A & B => C Ord[A] & Ord[B] => Ord[(A,B)] Int A
  11. 11. Scala List shapeless.HList Root type List HList Cons case class ::[A]( head: A, tail: List[A]) case class ::[H, T <: HList]( head: H, tail: T) Nil Nil (singleton) HNil (singleton) Type of 1 :: Nil ::[Int] Int :: HNil Type of 1 :: “a” :: Nil ::[Any] Int :: String :: HNil Type of 1 :: “a” :: true :: Nil ::[Any] Int :: String :: Boolean :: HNil
  12. 12. • • • • •
  13. 13. final class HListOps[L <: HList](l : L) { def at[N <: Nat](implicit at: At[L, N]): at.Out = at(l) } • • • • •
  14. 14. case class Person(name: String, age:Int)  String :: Int :: HNil (Int, Boolean)  Int :: Boolean :: HNil • • 2nd most important property (along with keeping precise types):
  15. 15. OddProduct[Int :: String :: Boolean :: Int :: Int :: HNil] Int :: HNil Boolean :: Int :: Int :: HNil Int :: String:: Boolean :: Int :: Int :: HNil A => B Odd[T <: HList] => Odd[H1 :: H2 :: T] A => B Odd[T <: HList] => Odd[H1 :: H2 :: T] A Odd[T :: HNil] Recursive step – resolving to the same implicit def
  16. 16. Generic.Aux[T, Repr] – Isomorphism, that allows us to get Repr from T and vice versa. Repr – some generic representation of T Property[Repr] – our Property is proved for type Repr. We can (almost always) derive the Property[T] by converting to/from Repr and using Property[Repr] Hint: Repr here is going to be an HList Looks similar to A & B => C. Let’s encode the proof!
  17. 17. Person(name: String, age: Int) Int :: HNil A & B => C Show[A] & Show[B] => Show[A :: B] Int A Show[Int] HNil A Show[HNil] String A Show[String] String :: Int :: HNil A & B => C Show[A] & Show[B] => Show[A :: B] Generic.Aux[Person, String :: Int :: HNil] A (macro) Generic[T] Person A & B => C Show[R] & Generic.Aux[T,R] => Show[T]
  18. 18. 1. 2. 3. 4. 5.
  19. 19. 1. 2. 3. 4. 5. 6.

×