Tuesday, June 15, 2010

Simplified case class Generator for Scalacheck

I just wrote a fairly handy generator for making very simple vanilla case classes. It basically uses the apply method defined in the companion of them to make things pretty simple. I am not sure if something similar is in the library already.

basically you can just type in your specification.

implicit val arbPoint = ArbFunc(Point.apply _)

and then arbitrary points will be provided as needed

If I posted the code here i have feeling it would get severely mangled so I put it in a gist:


I think it is a simpler way to make the generators for case classes where you don't care that much about constraining the members of the case class.

posted to the mailing list, waiting for moderation.

Monday, June 14, 2010

Working around Dependent Method Types with Structural Types

Until dependent method types move out of experimental status in the scala compiler (they can be enabled with -Xexperimental) we have been using Structural Typing to work around their absence.

Here's how were doing it:

First, Given:

trait AToB {
    type B
    def b : B

and an implementation:

trait AToInt extends AToB {
    final override type B = Int

object AToInt {
    def apply(x : Int) = new AToInt {
        final override val b = x

We would like to write a function with given any AToB
returns the type of B specified by that A:

if we had dependent method types we could write this as

def bOf[A <: AToB](a : A) : a.B = a.b

however this gives the error:

error: illegal dependent method type
          def bOf[A <: AToB](a : A) : a.B = a.b

To work around this however and still preserve type safety we have been doing this:

def bOf[AA <: AToB {type B = BB}, BB](a : AA) : BB = a.b

Basically we are using a structural type to fix the abstract type B in AToB to a concrete
type BB. This will enforce the type constraint that we want. There is one annoyance that remains
however and I haven't figured out a solution for it yet, the compiler is inferring the wrong type
for BB.

val x : Int = bOf(AToInt(5))

gives the compiler error:

error: inferred type arguments [java.lang.Object with AToInt,Nothing] do not conform to method bOf's type parameter bounds [AA <: AToB{type B = BB},BB]

yuck, the work around is to say:

val x : Int = bOf[AToInt, AToInt#B](AToInt(5))

Which will compile correctly.

A few more examples which will not compile:

trait AToString extends AToB {
    final override type B = String

object AToString {
    def apply(x : String) = new AToString {
        final override val b = x

//Will not compile
val x : String = bOf[AToInt, AToInt#B](AToInt(5))
//Will compile
val x : String = bOf[AToString, AToString#B](AToString("Good Times"))
//Will not compile
val x : Int = bOf[AToString, AToString#B](AToString("Good Times"))

Wednesday, February 3, 2010

Pot of coffee gone, Intellij + Scala + sbt + bash-support plugin = Continuous Unit Testing In The IDE

Got it working, sweet, no more neck strain looking back and forth from the terminal on every error, just their just a quick press away, don't even have to move the mouse and Intellij uses next occurrence to traverse between stacktrace elements in the active console.

Here's the patch for sbt it anyone is interested.


(previous post: http://scalide.blogspot.com/2010/02/trying-to-get-sbt-to-run-in-intellij.html)
(bash-support plugin for intellij http://plugins.intellij.net/plugin/?id=4230)
(mailing list posting http://groups.google.com/group/simple-build-tool/browse_thread/thread/a0cdaccc76c2384a)

Tuesday, February 2, 2010

Trying to get sbt to run in intellij with navigable errors and continuous compiles.

So close, time to brew another pot of coffee, roll up my sleeves, and get to hacking!


The dream of a 95% of the way there realtime compilation / unit test runner for scala in intellij is soooo close!

Wednesday, January 20, 2010

A Better Scala Enumeration Type

I am going to post a link to the Enum type that I wrote due to the limitations of the builtin Scala Version. I don't use the built in enumeration type anymore as I find it very limiting.

(source & test / example):

Originally I wrote this as answer to this question on StackOverflow, however felt that it would be useful here too.

Tuesday, January 5, 2010

Follow up to Product.hashCode collisions

After some experimentation here is the result that I came up. Note that you might need to increase the Heap Space to get it to run in the interpreter because of sort / removeDuplicates.

I posted it as a gist [http://gist.github.com/270117]

You should be able to just copy and paste it into a scala 2.8 interpreter
This yields a result of:

(ideal = 1000000.0, actual = 999880, uniqueRatio = 0.99988)
meaning a collision rate < .1%

Possible Collision Issue with Product.hashCode

First Off I am no expert at hashing algo's & perhaps this is some sort of Birthday Problem so I am not sure if what I am pointing out is actually a big issue. It would be interesting to see what would happen on a project that uses large hash maps with Products in it if the distribution at the bottom was improved.

Quick Summary:
Right now it seems like the hashCode for Products of Arity N is the same regardless of the actual class implementing it & that it doesn't distribute very well:

case class Point(x : Int, y : Int)
case class Point2(x : Int, y : Int)
(1,2).hashCode == Point(1,2).hashCode == Point2(1,2).hashCode == 3405

Welcome to Scala version 2.8.0.r20331-b20100101020206 (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_15).
List((1,2), (2,1), Point(1,2), Point(2,1), Point2(1,2), Point2(2,1)).map(_.hashCode)
res0: List[Int] = List(3405, 3445, 3405, 3445, 3405, 3445)

In a little more depth: I think this behavior is much better than in 2.7.5 where the ordering of the product elements did not affect the hashCode. (Point(x,y) would clash with Point(y,x))

in 2.7.5:

res0: List[Int] = List(1838716253, 1838716293, -1163646902, -1163646862, -270917823, -270917783)

Digging a little further on what this means for a distribution =>

Keep in mind that a big problem is that java's Integer.hashCode == the number being hashed, which is going to cause problems.

Using this code to get rudimentary collision distribution:

val tot = 500
val ideal = tot * tot * 1.0
val hashes = (for(x <- -(tot/2) until (tot/2); y <- -(tot/2) until (tot/2)) yield (x,y).hashCode ).toList
val hset = Set() ++ hashes
val hsSize = hset.size
val hlSize = hashes.removeDuplicates.size
println((ideal, hsSize, hsSize/ideal, hlSize, hlSize/ideal))

Here is the 2.7.5 result (takes a few minutes on a Core i7 920, removeDuplicates is terribly slow):

(250000.0, 20959,0.083836,20959,0.083836)

and Here is the 2.8 nightly result (surprisingly the same distribution, that takes only a few seconds):

(250000.0, 20959,0.083836,20959,0.083836)

Both cases are going to collide 90+% of the time (notice that changing tot to 100 reduces the collision % quite significantly so I suspect there is a quadratic relationship at play here)

Running with a tot =100 gives:
Still a 58% collide rate, but a lot better than the larger case.

Finally for the 3 Tuple cases with tot = 100

Perhaps I should look into a better case than just integers to see what the collision rates actually are like.