High Wizardry in the Land of Scala
Upcoming SlideShare
Loading in...5
×

Like this? Share it with your network

Share
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
4,100
On Slideshare
4,010
From Embeds
90
Number of Embeds
6

Actions

Shares
Downloads
71
Comments
0
Likes
12

Embeds 90

http://www.scoop.it 48
http://www.oscon.com 23
https://twitter.com 10
http://paper.li 6
http://webcache.googleusercontent.com 2
http://static.slidesharecdn.com 1

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide



































































Transcript

  • 1. High Wizardry in the Land of Scala Daniel Spiewak
  • 2. Agenda • Higher-Kinds • Typeclasses • Type-Level Encodings • Continuations
  • 3. Higher-Kinds • What is a “kind system”?
  • 4. Higher-Kinds • What is a “kind system”? • What is a “type system”?
  • 5. A type system is a tractable syntactic method for proving the absence of certain program behaviors by classifying phrases according to the kinds of values they compute. – Benjamin Pierce
  • 6. val i: Int = 42 val j: Int = 21 val s: String = "foo" val f: Int => String = { _.toString } val xs: List[Int] = List(1, 1, 2, 3, 5, 8)
  • 7. Values
  • 8. Types Values
  • 9. ??? Types Values
  • 10. Kinds Types Values
  • 11. Higher-Kinds • Type systems classify values • Kind systems classify types • Values are to types as types are to kinds
  • 12. type Int :: * type String :: * type (Int => String) :: * type List[Int] :: *
  • 13. type List :: ??? type Function1 :: ???
  • 14. type List :: * => * type Function1 :: (* × *) => *
  • 15. // id : Int => Int def id(x: Int) = x // Id :: * => * type Id[A] = A
  • 16. // id : ((Int => Int), Int) => Int def id(f: Int => Int, x: Int) = f(x) // Id :: ((* => *) × *) => * type Id[A[_], B] = A[B]
  • 17. val map: Map[Option[Any], List[Any]] = Map( Some("foo") -> List("foo", "bar", "baz"), Some(42) -> List(1, 1, 2, 3, 5, 8), Some(true) -> List(true, false, true, true)) // ugly cast! val xs: List[String] = map(Some("foo")).asInstanceOf[List[String]] // ditto! val ys: List[Int] = map(Some(42)).asInstanceOf[List[Int]]
  • 18. val map: HOMap[Option, List] = HOMap[Option, List]( Some("foo") -> List("foo", "bar", "baz"), Some(42) -> List(1, 1, 2, 3, 5, 8), Some(true) -> List(true, false, true, true)) // blissful type safety! val xs: List[String] = map(Some("foo")) // ditto! val ys: List[Int] = map(Some(42))
  • 19. // HOMap :: ((* => *) × (* => *)) => * class HOMap[K[_], V[_]](delegate: Map[K[Any], V[Any]]) { def apply[A](key: K[A]): V[A] = delegate(key.asInstanceOf[K[Any]]).asInstanceOf[V[A]] } object HOMap { def apply[K[_], V[_]](tuples: (K[Any], V[Any])*) = new HOMap[K, V](Map(tuples: _*)) } (credit: Jorge Ortiz)
  • 20. Higher-Kinds • Kind systems classify types • Values are to types as types are to kinds • “Higher” kinds are the kinds of type constructors • Type functions • Use any time one type is logically a function of another
  • 21. Typeclasses • Forget everything you know about classes • (it won’t help you anyway) • Instead of “class”, think “category” • If you’ve ever looked at Haskell…
  • 22. sum(List(1, 2, 3, 4)) // => 10 sum(List(3.14, 2.72)) // => 5.86 sum(List("me", "you")) // shouldn't compile!
  • 23. trait Num[A] { val zero: A def add(x: A, y: A): A } def sum[A](nums: List[A])(tc: Num[A]) = nums.foldLeft(tc.zero)(tc.add)
  • 24. object IntNum extends Num[Int] { val zero = 0 def add(x: Int, y: Int) = x + y } object DoubleNum extends Num[Double] { val zero = 0d def add(x: Double, y: Double) = x + y }
  • 25. // works! sum(List(1, 2, 3, 4))(IntNum) sum(List(3.14, 2.72))(DoubleNum)
  • 26. Typeclasses • This is functional, but ugly • We have to explicitly provide the relevant instance of Num[A]
  • 27. Typeclasses • This is functional, but ugly • We have to explicitly provide the relevant instance of Num[A]
  • 28. def sum[A](nums: Seq[A])(tc: Num[A]) = nums.foldLeft(tc.zero)(tc.add)
  • 29. def sum[A](nums: Seq[A])(implicit tc: Num[A]) = nums.foldLeft(tc.zero)(tc.add)
  • 30. object IntNum extends Num[Int] { val zero = 0 def add(x: Int, y: Int) = x + y } object DoubleNum extends Num[Double] { val zero = 0d def add(x: Double, y: Double) = x + y }
  • 31. implicit object IntNum extends Num[Int] { val zero = 0 def add(x: Int, y: Int) = x + y } implicit object DoubleNum extends Num[Double] { val zero = 0d def add(x: Double, y: Double) = x + y }
  • 32. sum(List(1, 2, 3, 4))(IntNum) sum(List(3.14, 2.72))(DoubleNum)
  • 33. sum(List(1, 2, 3, 4)) sum(List(3.14, 2.72))
  • 34. Typeclasses • Typeclasses are categories of types • If you have a set of types with well-defined commonalities, think about typeclasses • Collections in 2.8 • Numeric in 2.8
  • 35. Type-Level Encodings • Kinds make our types into superheroes • Typeclasses allow us to abstract over types • How can we abuse our new-found power?
  • 36. Type-Level Encodings • Kinds make our types into superheroes • Typeclasses allow us to abstract over types • How can we abuse our new-found power? • Maybe…data structures at the type level?
  • 37. Type-Level Encodings • HList is a linked-list implemented in types • …and values • Sort of like Tuple, but unbounded
  • 38. import HList._ val xs = 42 :: "foo" :: 3.14 :: HNil xs.head // => 42: Int xs.tail.head // => "foo": String
  • 39. val xs1 = 42 :: false :: HNil val xs2 = "Hello" :: "World" :: HNil val xs = xs1 ++ xs2 xs.head // => 42: Int xs.tail.tail.head // => "Hello": String
  • 40. object HList { sealed trait HList { type Head type Tail <: HList type Append[L <: HList] <: HList def head: Head def tail: Tail def ++[L <: HList](xs: L): Append[L] } // ... }
  • 41. val x: List[Int] = ... val y: List[Int] = ... x ++ y x 1 2 3 4 y 5 6 7 8 9
  • 42. val x: List[Int] = ... val y: List[Int] = ... x ++ y x 2 3 4 y 5 6 7 8 9
  • 43. val x: List[Int] = ... val y: List[Int] = ... x ++ y x 3 4 y 5 6 7 8 9
  • 44. val x: List[Int] = ... val y: List[Int] = ... x ++ y x 4 y 5 6 7 8 9
  • 45. val x: List[Int] = ... val y: List[Int] = ... x ++ y x’ y 5 6 7 8 9
  • 46. val x: List[Int] = ... val y: List[Int] = ... x ++ y x’ 4 y 5 6 7 8 9
  • 47. val x: List[Int] = ... val y: List[Int] = ... x ++ y x’ 3 4 y 5 6 7 8 9
  • 48. val x: List[Int] = ... val y: List[Int] = ... x ++ y x’ 2 3 4 y 5 6 7 8 9
  • 49. val x: List[Int] = ... val y: List[Int] = ... x ++ y x’ 1 2 3 4 y 5 6 7 8 9
  • 50. object HList { // ... final class HNil extends HList { type Head = Nothing type Tail = Nothing type Append[L <: HList] = L def head = error("Head of an empty HList") def tail = error("Tail of an empty HList") def ::[A](a: A) = HCons(a, this) def ++[L <: HList](xs: L) = xs } val HNil = new HNil }
  • 51. object HList { // ... case class HCons[A, B <: HList](head: A, tail: B) extends HList { type Head = A type Tail = B type Append[L <: HList] = HCons[Head, Tail#Append[L]] def ::[C](c: C) = HCons(c, this) def ++[L <: HList](xs: L) = head :: (tail ++ xs) } type ::[A, B <: HList] = HCons[A, B] }
  • 52. Type-Level Encodings • What about an nth(Int) function?
  • 53. Type-Level Encodings • What about an nth(Int) function? • Not today! • Church Numerals • λ-Calculus
  • 54. Type-Level Encodings • What about an nth(Int) function? • Not today! • Church Numerals • λ-Calculus • We could do a lot more • Just not in a 45 minute talk
  • 55. Continuations • Actually, delimited continuations • Very different from plain continuations! • Not like callcc • Not considered harmful • …though they can simulate goto!
  • 56. case class JumpException(i: Int) extends RuntimeException val res = try { val i = 42 println("before") throw JumpException(i) // basically: `break` val j: Int = i / 2 println("after") println(j + 2) j // needed for type checker } catch { case JumpException(i) => i } println("outside")
  • 57. val (res, func) = { val i = 42 println("before") (i, { j: Int => println("after") println(j + 2) }) } println("outside") func(res / 2) func(res / 6)
  • 58. val (res, func) = reset { val i = 42 println("before") val j = shift { (k: Int => Unit) => (i, k) } println("after") println(j + 2) } println("outside") func(res / 2) func(res / 6)
  • 59. val (res, func) = reset { val i = 42 println("before") val j = shift { (k: Int => Unit) => (i, k) } println("after") println(j + 2) } println("outside") func(res / 2) func(res / 6)
  • 60. val (res, func) = reset { val i = 42 println("before") val j = shift { (k: Int => Unit) => (i, k) } println("after") println(j + 2) } println("outside") func(res / 2) func(res / 6)
  • 61. val (res, func) = reset { val i = 42 println("before") val j = shift { (k: Int => Unit) => (i, k) } println("after") println(j + 2) } println("outside") func(res / 2) func(res / 6)
  • 62. def gen() = { var x = 1 var y = 1 while (true) { shift { (k: Unit => Result) => Result(x, k) } y += x x = y - x } } val res = reset { gen() error("It never ends that way, too!"): Result } val fib: Stream[Int] = res.toStream (credit: PEP-255)
  • 63. def gen() = { var x = 1 var y = 1 while (true) { shift { (k: Unit => Result) => Result(x, k) } y += x x = y - x } } val res = reset { gen() error("It never ends that way, too!"): Result } val fib: Stream[Int] = res.toStream (credit: PEP-255)
  • 64. Continuations • This is cool and all, but what’s it good for?
  • 65. Continuations • This is cool and all, but what’s it good for? • Not as much as you would think
  • 66. reset { for (i <- 0 to 10) { shift { (k: Unit => Unit) => i } } }
  • 67. reset { for (i <- 0 to 10) { shift { (k: Unit => Unit) => i } } }
  • 68. Continuations • This is cool and all, but what’s it good for? • Not as much as you would think • Nonblocking I/O • Multi-page wizards • Framework support is needed
  • 69. Conclusion • Higher-Kinds • Type Encodings • Classify types • Are really cool! • Typeclasses • Continuations • Categorize types • Powerful • ...but useless
  • 70. Questions?