implicit.ly

Scala software, hot off the presses

shapeless 1.1.0

A minor release of shapeless. The main changes include,

  • The addition of a Sized type for collections with statically known sizes.
  • The beginning of a collection of non-test examples.
  • The SBT project was missing an organization identifier. This has been fixed. Thanks to aloiscochard for catching and patching this.

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 and it also has a mailing list.

Filed under  //   Scala 2.10.0-SNAPSHOT   com.chuusai   shapeless  

shapeless 1.0.1

A minor release of shapeless mainly focussed on replacing arity-specific boilerplate with SBT based code generation.

  • The boilerplate for HList <-> Tuple conversion type class instances is now generated and covers all arities.
  • The boilerplate for ordinary function <-> HList function conversion type class instances is now generated and covers all arities.
  • The boilerplate for tuple Typeable type class instances is now generated and covers all arities.
  • Nat types and values are now generated.
  • There is now a type- and value-level conversion from Nats to Int, and there has been some minor reorganization of the Nat type classes.

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 and it also has a mailing list.

Filed under  //   Scala 2.10.0-SNAPSHOT   shapeless  

shapeless 1.0

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

```

```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

```

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.

Filed under  //   Scala 2.10.0-SNAPSHOT   default   shapeless  

scalariform 0.1.1

  • FIX: Leave PCDATA whitespace untouched inside a single-line XML tag (issue #27)
  • FIX: indent for indentLocalDefs on first line of function block (issue #24)
  • ParenExpr now allows newline after opening paren (issue #18)
  • FIX: spurious indentation in staggered dot expressions (issue #25)
  • Preserve newline before annotations (issue #28)
  • Add option to support CompactControlReadability style (issue #22) (thanks to by Owein Reese (https://github.com/wheaties) and Rose Toomey (https://github.com/rktoomey) for the patch
  • Preserve newline before anonymous function argument (issue #21)
  • Allow one-line anonymous function blocks
  • Fix parser crash on argument-less constructor annotations
  • Add PlaceScaladocAsterisksBeneathSecondAsterisk preference to conform to recommended Scaladoc style (issue #30)
  • FIX: Removal of space causing token merge in varargs and unary ops (http://scala-ide-portfolio.assembla.com/spaces/scala-ide/tickets/1000601)
  • Switch to sbt 0.11 build

Scalariform is a source code formatter for Scala.