<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3083788237966827171</id><updated>2011-12-19T04:24:55.536-08:00</updated><title type='text'>Jesper's Blog</title><subtitle type='html'>RandomThoughts &amp;gt;: Nothing &amp;lt;: Any</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-9077169168481122646</id><published>2010-05-13T14:19:00.000-07:00</published><updated>2010-05-14T02:53:37.524-07:00</updated><title type='text'>Scala Stream Fusion and Specialization, Part 2</title><content type='html'>&lt;span style="font-weight:bold;"&gt;Note:&lt;/span&gt; The full source code for this post can be found &lt;a href="http://svn.assembla.com/svn/metascala/src/test/stream/SpecializedIterators2.scala"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.scala-lang.org/sid/9"&gt;Scala specialization&lt;/a&gt; is maturing and in Scala 2.8 RC2 some parts of the standard library has been specialized (the function and tuple classes). So, it's time to update the stream fusion tests I wrote about in a &lt;a href="http://jnordenberg.blogspot.com/2010/03/scala-stream-fusion-and-specialization.html"&gt;previous blog post&lt;/a&gt; with proper specialization.&lt;br /&gt;&lt;br /&gt;It should be quite straight forward to fully specialize the filter and map iterators used in my previous post. This turns out to not be the case as the current specialization implementation contains a quite severe limitation:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style:italic;"&gt;A method is only specialized for a type parameter annotated as specialized if the method type signature contains the type parameter in a "naked" position (or an array of the "naked" type parameter).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;See &lt;a href="https://lampsvn.epfl.ch/trac/scala/ticket/3433"&gt;this ticket&lt;/a&gt; for more information. Here are some examples of how this limitation affects method specialization:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;trait A[@specialized T] {&lt;br /&gt;  def m1(t : T) : Boolean                  // Will be specialized for T&lt;br /&gt;  def m2(f : T =&gt; Boolean)                 // Will NOT be specialized for T&lt;br /&gt;  def m3[@specialized U](fn : T =&gt; U) : T  // Will be specialized for T, but NOT for U&lt;br /&gt;  def m4()                                 // Will NOT be specialized&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It easy to see how this will cause some problems when implementing specialized iterators and higher order functions.&lt;br /&gt;&lt;br /&gt;The iterator trait from my previous post has to be modified slightly as the &lt;span style="font-weight:bold;"&gt;next&lt;/span&gt; method would not get specialized due to the limitation mentioned above:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;trait SIterator[@specialized T] {&lt;br /&gt;  def hasNext : Boolean&lt;br /&gt;  def next() : T&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This interface is similar to the Java and Scala iterator interfaces.&lt;br /&gt;&lt;br /&gt;The implementations of array and map iterators are straight forward, but the filter iterator is quite tricky:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  final class FilterIterator[@specialized T](iter : SIterator[T], pred : T =&gt; Boolean) extends SIterator[T] {&lt;br /&gt;    private var hasElem = false&lt;br /&gt;    private var elem : T = findNext()&lt;br /&gt;&lt;br /&gt;    def hasNext = hasElem&lt;br /&gt;&lt;br /&gt;    def next() = {&lt;br /&gt;      val r = elem&lt;br /&gt;      findNext()&lt;br /&gt;      r&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def findNext() : T = {&lt;br /&gt;      while (iter.hasNext) {&lt;br /&gt;        elem = iter.next()&lt;br /&gt;&lt;br /&gt;        if (pred(elem)) {&lt;br /&gt;          hasElem = true&lt;br /&gt;          return elem&lt;br /&gt;        }&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      hasElem = false&lt;br /&gt;      elem&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Normally &lt;span style="font-weight:bold;"&gt;findNext&lt;/span&gt; wouldn't return anything, but that would cause it to not be specialized, so the return type must be set to &lt;span style="font-weight:bold;"&gt;T&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;The &lt;span style="font-weight:bold;"&gt;fold&lt;/span&gt; method is awkward to use as a dummy parameter has to be added so that all type parameters appear in "naked" positions:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def fold[@specialized T, @specialized U](iter : SIterator[T], fn : (U, T) =&gt; U, v : U, dummy : T) = {&lt;br /&gt;    var r = v&lt;br /&gt;&lt;br /&gt;    while (iter.hasNext) {&lt;br /&gt;      r = fn(r, iter.next())&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    r&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This leaves us with the following code for the map-filter-sum calculation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def mapFilterSum(a : Array[Int]) = {&lt;br /&gt;    val ai = new ArrayIterator(a, 0, a.length)&lt;br /&gt;    val s = new FilterIterator[Int](new MapIterator[Int, Int](ai, _ * 3 + 7), _ % 10 == 0)&lt;br /&gt;    fold[Int, Int](s, _ + _, 0, 0)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now to the benchmarks. Remember that we want to compare the performance to this while loop:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def mapFilterSumLoop(a : Array[Int]) = {&lt;br /&gt;    var i = 0&lt;br /&gt;    var r = 0&lt;br /&gt;&lt;br /&gt;    while (i &lt; a.length) {&lt;br /&gt;      val v = a(i) * 3 + 7&lt;br /&gt;&lt;br /&gt;      if ((v % 10) == 0)&lt;br /&gt;        r += v&lt;br /&gt;&lt;br /&gt;      i += 1&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    r&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Compiling with -optimize and running with -server gives the following benchmarks times:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Java version: 1.6.0_20&lt;br /&gt;Loop: (4936,-423600172)&lt;br /&gt;Specialized iterators: (5935,-423600172)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, 4936 microseconds for the while loop compared to 5935 microseconds for the specialized iterators, about 20% performance penalty. This relatively small difference in running times indicates that all boxing/unboxing has been eliminated. Nice indeed.&lt;br /&gt;&lt;br /&gt;It would be nice to clean up the syntax a bit for the filter and map operations. This turns out to be harder than expected, again due to the limitation in the specialization implementation. Dummy parameters have to be added to the &lt;span style="font-weight:bold;"&gt;filter&lt;/span&gt; and &lt;span style="font-weight:bold;"&gt;map&lt;/span&gt; methods:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  trait SIterator[@specialized T] {&lt;br /&gt;    def hasNext : Boolean&lt;br /&gt;    def next() : T&lt;br /&gt;    def filter(pred : T =&gt; Boolean, dummy : T) = new FilterIterator[T](this, pred)&lt;br /&gt;    def map[@specialized U](fn : T =&gt; U, dummy : T, dummy2 : U) = new MapIterator[T, U](this, fn)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Even with the dummy parameters the &lt;span style="font-weight:bold;"&gt;map&lt;/span&gt; method is not specialized correctly which leads to boxing and inferior performance.&lt;br /&gt;&lt;br /&gt;In conclusion I would say that specialization still needs some work before it can be useful in a collection library. It's a very powerful feature and hopefully it can be improved to reach its full potential in future Scala releases.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-9077169168481122646?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/9077169168481122646/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=9077169168481122646' title='31 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/9077169168481122646'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/9077169168481122646'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2010/05/scala-stream-fusion-and-specialization.html' title='Scala Stream Fusion and Specialization, Part 2'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>31</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-7390104310519482036</id><published>2010-03-06T09:39:00.000-08:00</published><updated>2010-03-07T05:02:04.706-08:00</updated><title type='text'>Scala Stream Fusion and Specialization</title><content type='html'>&lt;b&gt;Updated:&lt;/b&gt; Fixed code links and added view and stream benchmarks.&lt;br /&gt;&lt;br /&gt;Inspired by the successful results of &lt;a href="http://www.cse.unsw.edu.au/~dons/streams.html"&gt;Haskell stream fusion&lt;/a&gt; (see &lt;a href="http://donsbot.wordpress.com/2010/03/01/evolving-faster-haskell-programs-now-with-llvm/"&gt;Evolving Faster Haskell Programs (now with LLVM!)&lt;/a&gt; for some impressive optimizations) I was thinking if a similar concept is applicable to Scala collections. It turns out that with a combination of iterators and specialization it's possible to achieve similar optimizations in Scala.&lt;br /&gt;&lt;br /&gt;The goal of stream fusion is essentially to optimize code like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def scalaLibrarySum(a : Array[Int]) = a.map(i =&gt; i * 3 + 7).filter(i =&gt; (i % 10) == 0).foldLeft(0)(_ + _)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;into code like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def mapFilterSumLoop(a : Array[Int]) = {&lt;br /&gt;    var i = 0&lt;br /&gt;    var r = 0&lt;br /&gt;&lt;br /&gt;    while (i &lt; a.length) {&lt;br /&gt;      val v = a(i) * 3 + 7&lt;br /&gt;&lt;br /&gt;      if ((v % 10) == 0)&lt;br /&gt;        r += v&lt;br /&gt;&lt;br /&gt;      i += 1&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    r&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;If you run the &lt;b&gt;scalaLibrarySum&lt;/b&gt; method in Scala it will create two intermediate arrays with the results of the &lt;b&gt;map&lt;/b&gt; and &lt;b&gt;filter&lt;/b&gt; operations. This is totally unnecessary for this calculation as the functions passed to &lt;b&gt;filter&lt;/b&gt; and &lt;b&gt;map&lt;/b&gt; are side effect free and thus the result of the function applications can be performed lazily just before the result is needed in the fold operation. This is basically how the &lt;b&gt;mapFilterSumLoop&lt;/b&gt; method works.&lt;br /&gt;&lt;br /&gt;Besides creating intermediate arrays, boxing of primitive values must be avoided if we want to have any chance of competitive performance (the Haskell libraries contain specialized instances to avoid boxing). Fortunately Scala supports specialization of type parameters in version 2.8, which enables us to avoid boxing while still writing generic code. Unfortunately this feature seems to be quite buggy at the moment, just by playing around with a simple example I encountered two bugs (tickets &lt;a href="https://lampsvn.epfl.ch/trac/scala/ticket/3148"&gt;#3148&lt;/a&gt; and &lt;a href="https://lampsvn.epfl.ch/trac/scala/ticket/3149"&gt;#3149&lt;/a&gt;). So, the code below contain some specialization done by hand. Hopefully these bugs will be fixed so that the code can be fully generalized.&lt;br /&gt;&lt;br /&gt;The biggest difference compared to stream fusion in Haskell is that I use impure iterators in the Scala code. This is not as nice as the pure stream code used in Haskell, but it's a fact that Hotspot isn't nearly as good at optimizing pure functional code as GHC. Hotspot works best if fed imperative style loops.&lt;br /&gt;&lt;br /&gt;Here's the definitions of the specialized functions and iterators I use in the benchmark below:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  // Specialized Function1&lt;br /&gt;  trait Fn1[@specialized I, @specialized O] {&lt;br /&gt;    def apply(a : I) : O&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Specialized Function2&lt;br /&gt;  trait Fn2[@specialized I1, @specialized I2, @specialized O] {&lt;br /&gt;    def apply(a1 : I1, a2 : I2) : O&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Specialized iterator&lt;br /&gt;  trait SIterator[@specialized T] {&lt;br /&gt;    def hasMore : Boolean&lt;br /&gt;    def current : T&lt;br /&gt;    def next()&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In addition to this I've defined array, filter and map iterators. Unfortunately these are not generic due to the problems with the specialize feature:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  class IntArrayIterator(a : Array[Int], var index : Int, endIndex : Int) extends SIterator[Int] {&lt;br /&gt;    def next() = index += 1&lt;br /&gt;    def current = a(index)&lt;br /&gt;    def hasMore = index &lt; endIndex&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Optimally this would be: class FilterIterator[@specialized T](iter : SIterator[T], pred : Fn1[T, Boolean]) extends SIterator[T]&lt;br /&gt;  class FilterIterator(iter : SIterator[Int], pred : Fn1[Int, Boolean]) extends SIterator[Int] {&lt;br /&gt;    def hasMore = iter.hasMore&lt;br /&gt;&lt;br /&gt;    def next() = {&lt;br /&gt;      iter.next()&lt;br /&gt;      findNext()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def findNext() = {&lt;br /&gt;      while (iter.hasMore &amp;&amp; !pred(iter.current))&lt;br /&gt;        iter.next()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def current = iter.current&lt;br /&gt;&lt;br /&gt;    findNext()&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // Optimally this would be: class MapIterator[@specialized U][@specialized T](iter : SIterator[T], fn : Fn1[T, U]) extends SIterator[U]&lt;br /&gt;  class MapIterator(iter : SIterator[Int], fn : Fn1[Int, Int]) extends SIterator[Int] {&lt;br /&gt;    def next() = iter.next()&lt;br /&gt;    def current = fn(iter.current)&lt;br /&gt;    def hasMore = iter.hasMore&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The fold function is straightforward and generic:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def fold[@specialized T, @specialized U] (iter : SIterator[T], fn : Fn2[U, T, U], v : U) = {&lt;br /&gt;    var r = v&lt;br /&gt;&lt;br /&gt;    while (iter.hasMore) {&lt;br /&gt;      r = fn(r, iter.current)&lt;br /&gt;      iter.next()&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    r&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The map-filter-sum function can now be written using iterators:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  def mapFilterSum(a : Array[Int]) = {&lt;br /&gt;    val filter = new Fn1[Int, Boolean] {def apply(a : Int) = (a % 10) == 0}&lt;br /&gt;    val map = new Fn1[Int, Int] {def apply(a : Int) = a * 3 + 7}&lt;br /&gt;    val s = new FilterIterator(new MapIterator(new IntArrayIterator(a, 0, a.length), map), filter)&lt;br /&gt;    fold(s, new Fn2[Int, Int, Int] {def apply(a1 : Int, a2 : Int) = a1 + a2}, 0)&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The full iterator code can be found &lt;a href="http://svn.assembla.com/svn/metascala/src/test/stream/SpecializedIterators.scala"&gt;here&lt;/a&gt;. Compile the code using the latest Scala 2.8 build with the -Yspecialize flag. The optimize flag doesn't seem to have much effect on the performance.&lt;br /&gt;&lt;br /&gt;I've benchmarked four different implementations of the map-filter-sum calculation:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;The while loop shown above&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The while loop split up into map, filter and fold functions with intermediate array results passed between them&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The version using specialized iterators&lt;/li&gt;&lt;br /&gt;&lt;li&gt;The Scala library implementation shown above&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Same as Scala library function but with a view instead&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Same as Scala library function but with a stream instead&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;The benchmark is performed by taking the minimum execution time of 200 runs of each of the functions on an array of 1 million integers. Running the application with latest OpenJDK 7 (Hotspot version "build 17.0-b10") and the flags "-server -XX:CompileThreshold=100" I get the following results:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Loop: (4990,-423600172)&lt;br /&gt;Loop with intermediate arrays: (6690,-423600172)&lt;br /&gt;Specialized iterators: (5367,-423600172)&lt;br /&gt;Scala array: (46444,-423600172)&lt;br /&gt;Scala view: (39625,-423600172)&lt;br /&gt;Scala stream: (63210,-423600172)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The first result value is the minimum execution time in microseconds, the second value is the result of the calculation. As you can see the method using specialized iterators is almost as fast as the single while loop. Hotspot has inlined all the iterator code, not bad! Using intermediate arrays is about 25% slower than specialized iterators. Using the Scala library is about 7-9 times slower! Clearly this bad result is a consequence of boxing taking place. Using a view is fastest here as it also avoids intermediate array creation.&lt;br /&gt;&lt;br /&gt;The conclusion from this simple experiment is that it's certainly possible to write collection libraries with a nice high level interface and at the same time have excellent performance. When Scala specialization support is improved hopefully this power be available to all Scala programmers.&lt;br /&gt;&lt;br /&gt;The full benchmark code can be found &lt;a href="http://svn.assembla.com/svn/metascala/src/test/stream/Main.scala"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-7390104310519482036?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/7390104310519482036/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=7390104310519482036' title='12 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/7390104310519482036'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/7390104310519482036'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2010/03/scala-stream-fusion-and-specialization.html' title='Scala Stream Fusion and Specialization'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>12</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-2008299119303201836</id><published>2009-09-12T00:44:00.000-07:00</published><updated>2009-09-14T06:51:54.869-07:00</updated><title type='text'>Type Lists and Heterogeneously Typed Arrays</title><content type='html'>In previous blog posts (&lt;a href="http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html"&gt;HList in Scala&lt;/a&gt; and &lt;a href="http://jnordenberg.blogspot.com/2008/09/hlist-in-scala-revisited-or-scala.html"&gt;HList in Scala Revisited (or Scala Metaprogramming Works!)&lt;/a&gt;) I described a way to encode heterogeneously typed lists, HList, in Scala. This data type can be used as a generic replacement for the TupleX types found in the Scala library. In this post I will generalize the concept of type lists and introduce a new data type, HArray.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Note&lt;/span&gt;: the MetaScala code linked to in this post must be compiled using a recent Scala 2.8.0 build. I've given up on making it work with 2.7.x.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Type Lists&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In HList the types of the elements and the element values are intertwined in the same type. It doesn't have to be this way though and the types of the elements can be tracked separate from the actual element values. To do this we create an purely abstract type (it has no instances) which models a list of types, let's call it TList. Here's a simple implementation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  // Abstract base type&lt;br /&gt;  sealed trait TList&lt;br /&gt;&lt;br /&gt;  // The empty type list&lt;br /&gt;  final class TNil extends TList&lt;br /&gt;&lt;br /&gt;  // A pair of a type and a type list&lt;br /&gt;  final class TCons[H, T &lt;: TList] extends TList {&lt;br /&gt;    type Head = H&lt;br /&gt;    type Tail = T&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  // For infix notation&lt;br /&gt;  type ::[H, T &lt;: TList] = TCons[H, T]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;which would allow us to build type lists using infix notation, for example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  type SomeTypes = Int :: Boolean :: String :: TNil&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This is only the basic definition of TList, in practice you want to add lots of functionality to this type, like append, length, indexing, reverse etc. The full TList code is &lt;a href="http://svn.assembla.com/svn/metascala/src/metascala/TLists.scala"&gt;available in MetaScala&lt;/a&gt;. TList can be used for implementing HList, but also heterogeneously typed arrays which I describe below.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Heterogeneously Typed Arrays&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;With a heterogeneously typed array I mean an array where each element can have a unique type which is tracked at compile time (the length of the array is also tracked at compile time). This ensures that the element values are handled in a type safe way. The values are stored in an Array[Any] and are cast to the correct type when extracted from the array (remember that Java generics are implemented using casts as well so this is no different from using the TupleX classes, or a Java ArrayList). The element types are tracked using a TList. &lt;br /&gt;&lt;br /&gt;Here's part of the implementation which shows the prepend, append and nth methods:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;final class HArray[L &lt;: TList](private val elems : Array[Any]) extends HSeq[L] {&lt;br /&gt;    ...&lt;br /&gt;&lt;br /&gt;    def ::[T](v : T) = {&lt;br /&gt;      val a = new Array[Any](elems.length + 1)&lt;br /&gt;      a(0) = v&lt;br /&gt;      Array.copy(elems, 0, a, 1, elems.length)&lt;br /&gt;      new HArray[T :: L](a)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def :::[L2 &lt;: TList](l : HArray[L2]) = {&lt;br /&gt;      val a = new Array[Any](elems.length + l.elems.length)&lt;br /&gt;      Array.copy(l.elems, 0, a, 0, l.elems.length)&lt;br /&gt;      Array.copy(elems, 0, a, l.elems.length, elems.length)&lt;br /&gt;      new HArray[L2#Append[L]](a)&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    def apply[N &lt;: Nat](implicit nth : INth[N]) : L#Nth[N] = elems(nth.index).asInstanceOf[L#Nth[N]]&lt;br /&gt;    &lt;br /&gt;    ...&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Notice that the method implementations use simple array operations (array copy and indexing) so the performance should be comparable to using the TupleX classes in the Scala library (no benchmarks performed yet though). The full HArray implementation can be found &lt;a href="http://svn.assembla.com/svn/metascala/src/metascala/HArrays.scala"&gt;here&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;The HArray interface is similar to HList and virtually the same operations are supported. There are some &lt;a href="http://svn.assembla.com/svn/metascala/src/metascala/example/HArrayExample.scala"&gt;usage examples&lt;/a&gt; in MetaScala:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  // Create a HArray of an Int, Boolean and a pair&lt;br /&gt;  val a1 = 10 :: true :: (10.1, "Hello") :: HArrayNil&lt;br /&gt;&lt;br /&gt;  // Extract the second element, note that the element type&lt;br /&gt;  // information is preserved and we can safely perform a&lt;br /&gt;  // boolean and operation&lt;br /&gt;  val b = a1(_1) &amp;&amp; false&lt;br /&gt;&lt;br /&gt;  // Create another HArray using alternative syntax (faster)&lt;br /&gt;  val a2 = HArray(1.1, "string", false)&lt;br /&gt;&lt;br /&gt;  // Replace the second element in the list, it used to&lt;br /&gt;  // be a String, but now it's an Int&lt;br /&gt;  val a3 = a2.removeNth(_1).insert(_1, 14)&lt;br /&gt;&lt;br /&gt;  // Type information preserved, we can use an Int operation&lt;br /&gt;  // on the element&lt;br /&gt;  val i = a3(_1) / 2&lt;br /&gt;&lt;br /&gt;  // Append l2 to l1&lt;br /&gt;  val a4 = a1 ::: a2&lt;br /&gt;&lt;br /&gt;  // Statically check that the length of l4 is 6&lt;br /&gt;  type T = Equal[_6, a4.Size]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Other TList Applications&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;There are other applications for the TList type, for example it can be used for &lt;a href="http://svn.assembla.com/svn/metascala/src/metascala/OneOfs.scala"&gt;modeling type unions&lt;/a&gt; like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  case class OneOf[TS &lt;: TList](value : Any)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;which would be a lot easier to use than Either when you have more than two choices. A problem with this solution is that it wouldn't play well with Scala's pattern matcher, you would to add need unnecessary default cases for example. It should be possible to create type matching functions though to alleviate this problem. More work is needed in this area and it might be material for a future blog post.&lt;br /&gt;&lt;br /&gt;If you can think of other applications for type lists and sets I would be interested in hearing them.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-2008299119303201836?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/2008299119303201836/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=2008299119303201836' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/2008299119303201836'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/2008299119303201836'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2009/09/type-lists-and-heterogeneously-typed.html' title='Type Lists and Heterogeneously Typed Arrays'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-8302673659080073093</id><published>2009-04-21T07:12:00.000-07:00</published><updated>2009-04-21T08:44:59.328-07:00</updated><title type='text'>Equality, Mutability and Products</title><content type='html'>The thoughts in this post was sparked by a discussion on the scala-user mailing list. The discussion was about the &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Object.html#equals(java.lang.Object)"&gt;Object.equals()&lt;/a&gt; method and what its semantics should be. There are many different types of equality, but IMO the most usable one is if the expression a.equals(b) returns the same value regardless of when it's evaluated (provided the references a and b are constant), i.e. it's time invariant. If this was not the case, it would be quite impossible to implement &lt;a href="http://java.sun.com/javase/6/docs/api/java/lang/Object.html#hashCode()"&gt;Object.hashCode()&lt;/a&gt; in a useful way and you wouldn't be able to use objects as keys in a hash map or as members of a set.&lt;br /&gt;&lt;br /&gt;The Java standard library breaks this practice in a number of places, for example &lt;a href="http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html"&gt;java.util.ArrayList&lt;/a&gt; implements equals() as element equality which of course is not time invariant as the list can change over time (unless it's read only). I think the rationale behind this might be that there are no immutable collection classes in the Java libraries, and thus ArrayList is used for both mutable and immutable lists.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Equality for Mutable Case Classes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When using Scala case classes you automatically get an equals() and hashCode() implementation which calls the corresponding class fields methods. The implementation is the same regardless of whether the fields are mutable or not, so if you use vars the implementations will not be time invariant. For example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; case class A(var i : Int)&lt;br /&gt;defined class A&lt;br /&gt;&lt;br /&gt;scala&gt; val a1 = A(1)&lt;br /&gt;a1: A = A(1)&lt;br /&gt;&lt;br /&gt;scala&gt; val a2 = A(1)&lt;br /&gt;a2: A = A(1)&lt;br /&gt;&lt;br /&gt;scala&gt; a1 == a2&lt;br /&gt;res57: Boolean = true&lt;br /&gt;&lt;br /&gt;scala&gt; a1.hashCode&lt;br /&gt;res58: Int = -1085252538&lt;br /&gt;&lt;br /&gt;scala&gt; a1.i = 2&lt;br /&gt;&lt;br /&gt;scala&gt; a1 == a2&lt;br /&gt;res59: Boolean = false&lt;br /&gt;&lt;br /&gt;scala&gt; a1.hashCode&lt;br /&gt;res60: Int = -1085252537&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;How can we fix this? The Scala compiler only generates equals() and hashCode() implementations if we have not already implemented them in a super type (excluding java.lang.Object). So we can simply define a super trait for all mutable case classes:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;trait Mutable {&lt;br /&gt;  override def equals(v : Any) = super.equals(v)&lt;br /&gt;  override def hashCode = super.hashCode&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now we can easily define mutable case class with the default, time invariant equals() and hashCode() methods:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; case class A(var i : Int) extends Mutable&lt;br /&gt;defined class A&lt;br /&gt;&lt;br /&gt;scala&gt; val a1 = A(1)&lt;br /&gt;a1: A = A(1)&lt;br /&gt;&lt;br /&gt;scala&gt; val a2 = A(1)&lt;br /&gt;a2: A = A(1)&lt;br /&gt;&lt;br /&gt;scala&gt; a1 == a2&lt;br /&gt;res61: Boolean = false&lt;br /&gt;&lt;br /&gt;scala&gt; a1.hashCode&lt;br /&gt;res62: Int = 22213838&lt;br /&gt;&lt;br /&gt;scala&gt; a1.i = 2&lt;br /&gt;&lt;br /&gt;scala&gt; a1 == a2&lt;br /&gt;res63: Boolean = false&lt;br /&gt;&lt;br /&gt;scala&gt; a1.hashCode&lt;br /&gt;res64: Int = 22213838&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A more elegant solution is to define a Var trait and use this instead of vars in case classes, but this is not always a practical solution and it has some performance drawbacks.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Time Variant Equalily for Products&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So, what if I want to compare my case classes for element equality at a given moment in time? Turns out it's quite easy to implement such a function in Scala as all case classes implements the &lt;a href="http://www.scala-lang.org/docu/files/api/scala/Product.html"&gt;Product trait&lt;/a&gt;. Here's an example implementation (not thoroughly tested):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def equalElements(v1 : Any, v2 : Any) : Boolean = (v1, v2) match {&lt;br /&gt;  case (p1 : Product, p2 : Product) =&gt;&lt;br /&gt;    p1.getClass == p2.getClass &amp;&amp;&lt;br /&gt;    (0 until p1.productArity).forall(i =&gt; equalElements(p1.productElement(i), p2.productElement(i)))&lt;br /&gt;  case _ =&gt; v1 == v2&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This function has some limitations and won't work correctly with nested product and non-product objects. In this case a more type specialized solution is required.&lt;br /&gt;&lt;br /&gt;Example usage:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;scala&gt; val a1 = A(1)&lt;br /&gt;a1: A = A(1)&lt;br /&gt;&lt;br /&gt;scala&gt; val a2 = A(1)&lt;br /&gt;a2: A = A(1)&lt;br /&gt;&lt;br /&gt;scala&gt; equalElements(a1, a2)&lt;br /&gt;res68: Boolean = true&lt;br /&gt;&lt;br /&gt;scala&gt; a1.i = 2&lt;br /&gt;&lt;br /&gt;scala&gt; equalElements(a1, a2)&lt;br /&gt;res69: Boolean = false&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-8302673659080073093?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/8302673659080073093/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=8302673659080073093' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/8302673659080073093'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/8302673659080073093'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2009/04/equality-mutability-and-products.html' title='Equality, Mutability and Products'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-3419840825976345715</id><published>2009-02-23T06:29:00.000-08:00</published><updated>2009-02-23T07:02:04.733-08:00</updated><title type='text'>New Verson of InfoNode Docking Windows</title><content type='html'>(This post is not Scala related)&lt;br /&gt;&lt;br /&gt;I'm happy to announce the release of InfoNode Docking Windows 1.6.0. This release mainly contains fixes for some bugs which has been discovered since the previous release in 2007.&lt;br /&gt;&lt;br /&gt;A short description of InfoNode Docking Windows is that it's a Swing based docking windows library, similar to what you find in Eclipse, Netbeans, Visual Studio etc. but more light weight. It's very easy to integrate into an existing Swing application (heavy weight components are supported as well) and it's highly customizable using a powerful properties system. Much of the window behaviors/looks can be tweaked with very little code. A number of themes are included in the distribution, and it's easy to create custom themes.&lt;br /&gt;&lt;br /&gt;Well, a Web Start application says more than a thousand words, so why not try the &lt;a href="http://infonode.net/index.html?idwdemo"&gt;demos&lt;/a&gt; for yourself.&lt;br /&gt;&lt;br /&gt;InfoNode Docking Windows is dual licensed under the GPL and commercial licenses. The GPL version can be downloaded from &lt;a href="http://sourceforge.net/project/showfiles.php?group_id=110922"&gt;this page&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;For more information, see the &lt;a href="http://www.infonode.net"&gt;InfoNode web page&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-3419840825976345715?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/3419840825976345715/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=3419840825976345715' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/3419840825976345715'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/3419840825976345715'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2009/02/new-verson-of-infonode-docking-windows.html' title='New Verson of InfoNode Docking Windows'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-5881089427904716339</id><published>2008-10-04T00:59:00.000-07:00</published><updated>2008-10-04T06:11:11.070-07:00</updated><title type='text'>Functional Purity in Scala</title><content type='html'>An important concept in functional programming is &lt;a href="http://en.wikipedia.org/wiki/Pure_function"&gt;pure functions&lt;/a&gt;. The properties of pure functions means that they are easily verifiable and allows concurrent execution (an important advantage on today's multi-core machines). You can write pure functions in pretty much all programming languages, but AFAIK there are only two popular programming languages that verifies the purity at compile time: &lt;a href="http://haskell.org/"&gt;Haskell&lt;/a&gt; and &lt;a href="http://www.digitalmars.com/d"&gt;D&lt;/a&gt;. In Haskell you can't use side effects or externally visible variables if you don't explicitly indicate so using monads in your function signature. D takes a different approach where the default is that you are allowed to use side effects and variables in your functions, and you must explicitly mark them as pure, see &lt;a href="http://www.digitalmars.com/d/2.0/accu-functional.pdf"&gt;this presentation&lt;/a&gt; for more information. The difference in the implementations are surely because Haskell was designed from the start to be pure, but in D pure functions was added in version 2.0 of the language.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Pure Functions in Scala&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;I've been thinking about the best approach to implement pure function verification in the Scala compiler. An approach similar to the one in D would fit a lot better than the one used in Haskell (which would break all existing code and cause some problems due to strict evaluation). A solution using annotations would be quite simple to implement:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Pure extends Annotation&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In practice you want to define this as a runtime annotation in Java, but let's stick to Scala here. Now you can mark a function/method as pure:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;@Pure def pureFunc(x : Int, y : Int) = x + y&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;There are some rules that the compiler must verify for a pure method/function:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Only calls to pure functions are allowed. This requires that a large number of functions in the Scala library must be marked using the pure annotation otherwise it will be impossible to write new pure functions.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Non-local vars can't be read or written. Local vars can be used in a pure function (as an accumulator for example), but you can't access static variables or variables reachable from the arguments.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;A pure method can only be overridden by a pure method, and an interface method defined as pure can only be implemented as a pure method.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So far things are simple, but the restrictions imposed are quite severe, for example we can't create an array inside a pure function and use locally as this would result in calls to the non-pure array apply/update methods. Clearly this has to be allowed, which leads to the concept of "semi-pure" functions.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Semi-Pure Functions&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Let's define the concept of a semi-pure function/method:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class SemiPure extends Annotation&lt;br /&gt;class Pure extends SemiPure&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see a Pure function is a subtype of SemiPure, so anywhere a SemiPure function is required a Pure function can be used, for example a method marked as SemiPure can be overridden by a Pure method (but not the other way around). Here's an example of a semi-pure method:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  case class Var(var value : Int) {&lt;br /&gt;    @SemiPure def inc = {&lt;br /&gt;      value += 1  // Ok, we can modify fields in this object&lt;br /&gt;      value&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The following compilation rules applies to a semi-pure function:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;It can call pure and semi-pure functions.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It can use local variables.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It can read and write variables reachable from its arguments. This includes the implicit this argument passed for class methods, so a class method can read/write fields of a class instance.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;It can only be overridden by/implemented as a semi-pure or pure method.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So what use do we have for semi-pure functions? Well, they allow us to loosen the restrictions placed on pure functions somewhat: a pure function may call a semi-pure function if, and only if, all the argument values passed are created locally or are "invariant". "Invariant" is a term I borrowed from D, it's basically a deeply immutable value, i.e. it's an immutable value that only contain invariant values :). For example, List[Int] is invariant, but List[Array[Int]] is not invariant even though List[Array[Int]] is an immutable type.&lt;br /&gt;&lt;br /&gt;So with this loosened restriction you can for example define a function that creates an array and updates it in a loop, and it can still be a pure function. A quite powerful concept that blends the imperative and purely functional programming styles.&lt;br /&gt;&lt;br /&gt;Here's an example of a legal pure function that calls a semi-pure function (let's assume the method List[T].head is defined as pure):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt; case class Var(var value : Int) {&lt;br /&gt;    @SemiPure def inc = {&lt;br /&gt;      value += 1&lt;br /&gt;      value&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  @Pure def pureFunc(l : List[Var]) = {&lt;br /&gt;    val x = l.head       // Ok, pure method called&lt;br /&gt;    val v2 = Var(10)     // Object created locally&lt;br /&gt;    v2.inc               // Ok, call of semi-pure function with locally created object&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;However, this is not allowed:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  @Pure def pureFunc2(l : List[Var]) = {&lt;br /&gt;    val x = l.head  // Ok, pure method called&lt;br /&gt;    x.inc           // Error: semi-pure method called on variant external object&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;as it would result in an externally visible modification.&lt;br /&gt;&lt;br /&gt;How to verify that a type is invariant is a problem that needs to be explored further. It should be doable with an addition of an immutable/invariant annotation, but there are some complications with subtyping and type parameters.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Function Objects&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;One more thing needs to be solved: how to declare a pure function parameter for a &lt;a href="http://en.wikipedia.org/wiki/Higher-order_function"&gt;higher-order function&lt;/a&gt;. A quite simple solution is to create traits for pure and semi-pure functions and mix them with the function types. For example if you want to define a pure map function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;  trait TSemiPure&lt;br /&gt;  trait TPure extends TSemiPure&lt;br /&gt;  &lt;br /&gt;  @Pure def map[T, U](l : List[T], fn : (T =&gt; U) with TPure) : List[U] = &lt;br /&gt;    if (l.isEmpty) Nil else fn(l.head) :: map(l.tail, fn)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The TPure type would simply mean that the function objects apply method is considered pure by the compiler. There would be some restrictions on how the (semi-)pure traits would be allowed to be mixed in by the programmer. Another, maybe simpler, option is to create a new set of (Semi)PureFunction0-22 traits that extends the existing Function0-22 traits.&lt;br /&gt;&lt;br /&gt;For lambda expressions the compiler could automatically infer if the function is pure, semi-pure or impure, and use the correct trait. During eta expansion the correct trait can be used depending on the annotation of the method/function expanded.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Final Words&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Using the constructs I've presented in this post I think it would be feasible to implement checking of functional purity in the Scala compiler without too much effort. Hopefully this will result in a SIP in the near future, so that Scala hackers can utilize the powerful tool of statically checked pure functions.&lt;br /&gt;&lt;br /&gt;I'm sure I've made some error or missed something along the way, so I'm grateful for any comments/corrections you might have.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-5881089427904716339?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/5881089427904716339/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=5881089427904716339' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/5881089427904716339'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/5881089427904716339'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2008/10/functional-purity-in-scala.html' title='Functional Purity in Scala'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-7405255734147642352</id><published>2008-09-07T11:12:00.000-07:00</published><updated>2008-09-07T12:30:08.430-07:00</updated><title type='text'>HList in Scala Revisited (or Scala Metaprogramming Works!)</title><content type='html'>The Scala compiler team listened to my request for supporting recursive type projections (&lt;a href="http://lampsvn.epfl.ch/trac/scala/ticket/1291"&gt;ticket #1291&lt;/a&gt;) and has added experimental support for it. If you have a new build of the compiler (latest nightly or Eclipse plugin will do) you can enable it by add the compiler option "-Yrecursion x", where x is the maximum recursion depth allowed. Thanks to the EPFL team for the help, and particularly Geoffrey for implementing the fix.&lt;br /&gt;&lt;br /&gt;The HList code I presented in my previous &lt;a href="http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html"&gt;post&lt;/a&gt; now compiles without errors. I've setup a &lt;a href="http://www.assembla.com/wiki/show/metascala"&gt;project at Assembla&lt;/a&gt; with the &lt;a href="http://trac.assembla.com/metascala/browser/src/metascala/HLists.scala"&gt;HList&lt;/a&gt; code and other metaprogramming constructs like booleans, natural numbers, integers, units etc. The library is in pre-alpha stage and there's lots of work to be done, for example the HList type is missing many methods found in the Scala List type.&lt;br /&gt;&lt;br /&gt;Basically anything you can do with a normal List you can do with a HList, but all operations are type safe on an element by element basis. Here is some example code using HLists:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;object HListExample {&lt;br /&gt;  import HLists._&lt;br /&gt;  import Nats._&lt;br /&gt;  import Utils._&lt;br /&gt;  &lt;br /&gt;  // Create a HList of an Int, Boolean and a pair&lt;br /&gt;  val l1 = 10 :: true :: (10.1, "Hello") :: HNil&lt;br /&gt;  &lt;br /&gt;  // Extract the second element, note that the element type &lt;br /&gt;  // information is preserved and we can safely perform a &lt;br /&gt;  // boolean and operation&lt;br /&gt;  l1.nth[_1] &amp;&amp; false&lt;br /&gt;  &lt;br /&gt;  // Create another HList, note the use of an operator in &lt;br /&gt;  // the type expression &lt;br /&gt;  val l2 : Double :: String :: Boolean :: HNil = 1.1 :: "string" :: false :: HNil&lt;br /&gt;  &lt;br /&gt;  // Replace the second element in the list, it used to&lt;br /&gt;  // be a String, but now there's an Int inserted&lt;br /&gt;  val l3 = l2.remove[_1].insert(_1, 14)&lt;br /&gt;  &lt;br /&gt;  // Type information is preserved, we can use an Int operation&lt;br /&gt;  // on the element&lt;br /&gt;  l3.nth[_1] * 10&lt;br /&gt;&lt;br /&gt;  // Append l2 to l1&lt;br /&gt;  val l4 = l1 ::: l2&lt;br /&gt;&lt;br /&gt;  // Statically check that the length of l4 is 6&lt;br /&gt;  type T = Equal[_6, l4.type#Length]&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So, what are HLists useful for, besides being a fancy replacement for tuple types? Well, they can for example be used to implement a completely type safe object oriented programming language with support for delegation, subtyping etc. inside Scala. I will get back to that in a later blog entry.&lt;br /&gt;&lt;br /&gt;The project code also contains a simple example of a type safe &lt;a href="http://trac.assembla.com/metascala/browser/src/metascala/Units.scala"&gt;units library&lt;/a&gt;. Here's a usage example:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;object UnitsTest {&lt;br /&gt;  import Units._&lt;br /&gt;  import Integers._&lt;br /&gt;  &lt;br /&gt;  val dist : Length = measure(2.3) * m&lt;br /&gt;  val time : Time = measure(1.7) * s&lt;br /&gt;  val speed : Speed = dist / time&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;All units are checked at compile time, so you can't assign a length to a time variable for example.&lt;br /&gt;&lt;br /&gt;There are lots of other use cases for metaprogramming and the library will continue to grow over time. However, there are some issues with metaprogramming in Scala, one being the speed of the compiler. Compiling types which expands to long paths can sometimes take a very long time. I have submitted a &lt;a href="http://lampsvn.epfl.ch/trac/scala/ticket/1327"&gt;ticket&lt;/a&gt; about this too. Hopefully some optimizations are made to alleviate the problem. Meanwhile, I think certain applications of metaprogramming, for example compile time checked bounded integers, will put to much stress on the compiler and should probably be avoided.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-7405255734147642352?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/7405255734147642352/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=7405255734147642352' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/7405255734147642352'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/7405255734147642352'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2008/09/hlist-in-scala-revisited-or-scala.html' title='HList in Scala Revisited (or Scala Metaprogramming Works!)'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3083788237966827171.post-2698112983666478561</id><published>2008-08-31T11:40:00.000-07:00</published><updated>2008-08-31T16:06:10.845-07:00</updated><title type='text'>HList in Scala</title><content type='html'>This is my first blog post about Scala, so be gentle in your criticism :).&lt;br /&gt;&lt;br /&gt;I've been trying to implement a linked list of heterogeneously typed elements in Scala, similar to &lt;a href="http://homepages.cwi.nl/~ralf/HList"&gt;HList&lt;/a&gt; for Haskell. This data type can for example be used as a replacement for all the TupleX types in the Scala standard library. A simple implementation of the HList data type in Scala might look like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;object HListTest {&lt;br /&gt;  sealed trait HList&lt;br /&gt;&lt;br /&gt;  final class HNil extends HList {&lt;br /&gt;    def ::[T](v : T) = HCons(v, this)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  val HNil = new HNil()&lt;br /&gt;&lt;br /&gt;  final case class HCons[H, T &lt;: HList](head : H, tail : T) extends HList {&lt;br /&gt;    def ::[T](v : T) = HCons(v, this)&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  type ::[H, T &lt;: HList] = HCons[H, T]&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A list of arbitrary length can now be created:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;val list : Int :: String :: Boolean :: HNil = 10 :: "hello" :: true :: HNil&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Fine, now let's try to implement something more advanced like the append function:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;case class Appender[L1 &lt;: HList, L2 &lt;: HList, Result &lt;: HList](fn : (L1, L2) =&gt; Result)&lt;br /&gt;{&lt;br /&gt;  def apply(l1 : L1, l2 : L2) = fn(l1, l2)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def append[L1 &lt;: HList, L2 &lt;: HList, Result &lt;: HList](l1 : L1, l2 : L2)&lt;br /&gt;  (implicit fn : Appender[L1, L2, Result]) : Result = fn(l1, l2)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Note that the return type of the append function depends on the argument types. To use the append function we must provide two implicit functions that create instances of the Appender class for appending to the empty list and to a cons list:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;implicit def nilAppender[L &lt;: HList] : Appender[HNil, L, L] =&lt;br /&gt;  Appender((v : HNil, l : L) =&gt; l)&lt;br /&gt;&lt;br /&gt;implicit def consAppender[H, T &lt;: HList, L2 &lt;: HList, R &lt;: HList]&lt;br /&gt;  (implicit fn : Appender[T, L2, R]) : Appender[HCons[H, T], L2, HCons[H, R]] =&lt;br /&gt;  Appender[HCons[H, T], L2, HCons[H, R]]((l1 : HCons[H, T], l2 : L2) =&gt; HCons(l1.head, fn(l1.tail, l2)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A simple test case:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;append(HNil, HNil)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What? Compiler error, no implicit argument found? Closer examination of the error message indicates that the Scala compiler has bound the Result type parameter of the append function to Nothing, and then it tried to find an implicit matching this type. This will obviously not work. Explicitly passing the nilAppender works:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;append(HNil, HNil)(nilAppender)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;It seems the return type of a function can't be inferred from implicit arguments, we must be able to specify the return type of append only with the help of the non-implicit parameters. This is unfortunately an example where the Scala type inferer is not as powerful as the one in Haskell.&lt;br /&gt;&lt;br /&gt;Game over? No, we have one more ace up our sleeve: abstract types. Let's declare the return type of the append function as an abstract type in the HList trait, and modify the append and implicit functions to use type projections:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;sealed trait HList {&lt;br /&gt;  type Append[L &lt;: HList] &lt;: HList&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;final class HNil extends HList {&lt;br /&gt;  type Append[L &lt;: HList] = L&lt;br /&gt;&lt;br /&gt;  def ::[T](v : T) = HCons(v, this)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;final case class HCons[H, T &lt;: HList](head : H, tail : T) extends HList {&lt;br /&gt;  type Append[L &lt;: HList] = HCons[H, T#Append[L]]&lt;br /&gt;&lt;br /&gt;  def ::[T](v : T) = HCons(v, this)&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;def append[L1 &lt;: HList, L2 &lt;: HList](l1 : L1, l2 : L2)&lt;br /&gt;  (implicit fn : Appender[L1, L2, L1#Append[L2]]) : L1#Append[L2] = fn(l1, l2)&lt;br /&gt;&lt;br /&gt;implicit def nilAppender[L &lt;: HList] : Appender[HNil, L, L] = &lt;br /&gt;  Appender((v : HNil, l : L) =&gt; l)&lt;br /&gt;&lt;br /&gt;implicit def consAppender[H, T &lt;: HList, L2 &lt;: HList, R &lt;: HList]&lt;br /&gt;  (implicit fn : Appender[T, L2, T#Append[L2]]) : Appender[HCons[H, T], L2, HCons[H, T]#Append[L2]] =&lt;br /&gt;  Appender[HCons[H, T], L2, HCons[H, T]#Append[L2]]((l1 : HCons[H, T], l2 : L2) =&gt; HCons(l1.head, fn(l1.tail, l2)))&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now the simple test case works:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;append(HNil, HNil)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A more advanced test works as well:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;append(true :: HNil, 10 :: HNil).tail.head * 3&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Nice! Have we implemented a type safe append function for heterogeneous lists of arbitrary length? Unfortunately not:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;append(true :: "hello" :: HNil, 10 :: HNil)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will cause an "illegal cyclic reference" compiler error. A type path can't contain the same type declaration twice, even though it or the enclosing type has different type arguments. In this case the HCons#Append type will be recursively evaluated twice for the first list type. &lt;br /&gt;&lt;br /&gt;I've filed an &lt;a href="http://lampsvn.epfl.ch/trac/scala/ticket/1291"&gt;enhancement ticket&lt;/a&gt; to remove this restriction. Hopefully it will be implemented some time in the near future, so the full power of abstract types and type projections can be utilized. In fact, there are many more things that can be implemented if this restriction is removed, see C++ &lt;a href="http://www.boost.org/doc/libs/release/libs/mpl/doc/index.html"&gt;MPL&lt;/a&gt; and &lt;a href="http://www.boost.org"&gt;Boost&lt;/a&gt; for some examples. &lt;br /&gt;&lt;br /&gt;So, this is the current state of my exploration of Scala's wonderful type system. Unfortunately, at the moment it seems like HList can't be fully implemented in Scala. I'm grateful for comments proving me wrong though :)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3083788237966827171-2698112983666478561?l=jnordenberg.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://jnordenberg.blogspot.com/feeds/2698112983666478561/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=3083788237966827171&amp;postID=2698112983666478561' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/2698112983666478561'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3083788237966827171/posts/default/2698112983666478561'/><link rel='alternate' type='text/html' href='http://jnordenberg.blogspot.com/2008/08/hlist-in-scala.html' title='HList in Scala'/><author><name>Jesper Nordenberg</name><uri>http://www.blogger.com/profile/07589508061874776093</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry></feed>
