Permalink
Browse files

Added notes for implicit.ly.

  • Loading branch information...
1 parent b60a89a commit 48b1604728c8c7198c3b866a176000ee1a74c3dc @milessabin committed Dec 19, 2011
Showing with 177 additions and 0 deletions.
  1. +172 −0 notes/1.0.markdown
  2. +5 −0 notes/about.markdown
View
@@ -0,0 +1,172 @@
+Selected highlights of this 1.0 release of shapeless include,
+
+* A new encoding of polymorphic function values which optionally supports
+ type specific cases, and which is interoperable with Scala's ordinary
+ monomorphic function values.
+
+```scala
+ // choose is a function from Sets to Options with no type specific cases
+ object choose extends (Set ~> Option) {
+ def default[T](s : Set[T]) = s.headOption
+ }
+
+ // choose is convertible to an ordinary monomorphic function value
+ val lo = List(Set(1, 3, 5), Set(2, 4, 6)) map choose
+ lo == List(Option(1), Option(2))
+
+ // size is a function from values of arbitrary type to a 'size' which is
+ // defined via type specific cases
+ object size extends (Id ~> Const[Int]#λ) {
+ def default[T](t : T) = 1
+ }
+ implicit def sizeInt = size.λ[Int](x => 1)
+ implicit def sizeString = size.λ[String](s => s.length)
+ implicit def sizeList[T] = size.λ[List[T]](l => l.length)
+ implicit def sizeOption[T](implicit cases : size.λ[T]) =
+ size.λ[Option[T]](t => 1+size(t.get))
+ implicit def sizeTuple[T, U](implicit st : size.λ[T], su : size.λ[U]) =
+ size.λ[(T, U)](t => size(t._1)+size(t._2))
+
+ size(23) == 1
+ size("foo") == 3
+ size((23, "foo")) == 4
+```
+
+* An implementation of [Scrap your Boilerplate with Class](http://goo.gl/pR1OV)
+ which provides generic map and fold operations over arbitrarily nested data
+ structures,
+
+```scala
+ val nested = List(Option(List(Option(List(Option(23))))))
+
+ val succ = everywhere(inc)(nested)
+ succ == List(Option(List(Option(List(Option(24))))))
+```
+
+* A `Typeable` type class which provides a type safe cast operation.
+
+```scala
+ val a : Any = List(Vector("foo", "bar", "baz"), Vector("wibble"))
+
+ val lvs : Option[List[Vector[String]]] = a.cast[List[Vector[String]]]
+ lvs.isDefined == true
+
+ val lvi : Option[List[Vector[Int]]] = a.cast[List[Vector[Int]]]
+ lvi.isEmpty == true
+```
+
+* The mother of all Scala `HList`'s, which amongst other things,
++ is covariant.
+
+```scala
+ trait Fruit
+ case class Apple() extends Fruit
+ case class Pear() extends Fruit
+
+ type FFFF = Fruit :: Fruit :: Fruit :: Fruit :: HNil
+ type APAP = Apple :: Pear :: Apple :: Pear :: HNil
+
+ val a : Apple = Apple()
+ val p : Pear = Pear()
+
+ val apap : APAP = a :: p :: a :: p :: HNil
+ val ffff : FFFF = apap // APAP <: FFFF
+```
+
++ has a map operation, applying a polymorphic function value (possibly
+ with type specific cases) across its elements. This means that it
+ subsumes both typical `HList`'s and also `KList`'s (`HList`'s whose
+ elements share a common outer type constructor).
+
+```scala
+ type SISS = Set[Int] :: Set[String] :: HNil
+ type OIOS = Option[Int] :: Option[String] :: HNil
+
+ val sets : SISS = Set(1) :: Set("foo") :: HNil
+ val opts : OIOS = sets map choose
+ opts == Option(1) :: Option("foo") :: HNil
+```
+
++ has a zipper for traversal and persistent update.
+
+```scala
+ val l = 1 :: "foo" :: 3.0 :: HNil
+
+ val l2 = l.toZipper.right.put("wibble", 45).toHList
+ l2 == 1 :: ("wibble", 45) :: 3.0 :: HNil
+
+ val l3 = l.toZipper.right.delete.toHList
+ l3 == 1 :: 3.0 :: HNil
+
+ val l4 = l.toZipper.last.left.insert("bar").toHList
+ l4 == 1 :: "foo" :: "bar" :: 3.0 :: HNil, l5)
+```
+
++ has a `unify` operation which converts it to an `HList` of elements
+ of the least upper bound of the original types.
+
+```scala
+ val ffff = apap.unify // type inferred as FFFF
+```
+
++ supports conversion to an ordinary Scala `List` of elements of the
+ least upper bound of the original types.
+
+```scala
+ val lf = apap.toList // type inferred as List[Fruit]
+ lf == List(a, p, a, p)
+```
+
++ has a `Typeable` type class instance, allowing, eg. vanilla
+ `List[Any]`'s or `HList`'s with elements of type `Any` to be safely
+ cast to precisely typed `HList`'s.
+
+```scala
+ val ffff : FFFF = apap.unify // discard precise typing
+ val apap2 : Option[APAP] = ffff.cast[APAP] // reestablish precise typing
+ apap2.get == apap
+```
+
+These last three bullets make this `HList` dramatically more practically
+useful than `HList`'s are typically thought to be: normally the full
+type information required to work with them is too fragile to cross subtyping
+or I/O boundaries. This implementation supports the discarding of precise
+information where necessary (eg. to serialize a precisely typed record after
+construction), and its later reconstruction (eg. a weakly typed deserialized
+record with a known schema can have it's precise typing reestabilished).
+
+* Conversions between tuples and `HList`'s, and between ordinary Scala
+ functions of arbitrary arity and functions which take a single
+ corresponding `HList` argument. One application of this is the `liftO`
+ function which lifts an ordinary function of arbitrary arity into `Option`.
+
+```scala
+ // Round trip from tuple to HList and back
+ val t1 = (23, "foo", 2.0, true)
+
+ val l1 = t1.hlisted
+ h1 == 23 :: "foo" :: 2.0 :: true :: HNil
+
+ val t2 = l1.tupled
+ t1 == t2
+
+ // Lift these ordinary Scala function values into Option
+ val sum : (Int, Int) => Int = _ + _
+ val prd : (Int, Int, Int) => Int = _ * _ * _
+
+ // Nb. liftO abstracts over the arity of its function arguments
+ val sumO = liftO(sum) // (Option[Int], Option[Int]) => Option[Int]
+ val prdO = liftO(prd) // (Option[Int], Option[Int], Option[Int]) => Option[Int]
+
+ val s1 = sumO(Some(1), Some(2))
+ s1 == Option(3)
+
+ val s2 = sumO(Some(1), None)
+ s2 == None
+
+ val p1 = prdO(Some(2), Some(3), Some(4))
+ p1 == Option(24)
+
+ val p2 = prdO(Some(2), None, Some(4))
+ p2 == None
+```
View
@@ -0,0 +1,5 @@
+[shapeless](https://github.com/milessabin/shapeless) is an exploration of
+type class and dependent type based generic programming in Scala.
+
+A series of articles on the implementation techniques used will appear
+[here](http://www.chuusai.com/blog).

0 comments on commit 48b1604

Please sign in to comment.