Path Dependent Types in Scala

| Comments

Often confusing to newer Scala developers, “Inner classes” in Scala do not behave the way they do in many other languages. Thus, they can be perceived to be ‘inconsistent’ from expectations in their behavior.

It isn’t possible, given the following class definition:

1
2
3
4
class Outer {
  class Inner
  def put(inner: Inner): Unit = ()
}

To instantiate the Inner class directly:

1
2
3
4
scala> new Outer.Inner
<console>:12: error: not found: value Outer
       new Outer.Inner
           ^

Instead, we need an instance of Outer to create an Inner instance:

1
2
3
4
val outer1 = new Outer
val inner1 = new outer1.Inner
val outer2 = new Outer
val inner2 = new outer2.Inner

In other words, the path to an Inner instance depends upon the Outer instance. Note as well that there is no true relationship between outer1.Inner and outer2.Inner:

1
2
3
4
5
6
7
scala> outer1.put(inner1)

scala> outer1.put(inner2)
<console>:16: error: type mismatch;
 found   : outer2.Inner
 required: outer1.Inner
       outer1.put(inner2)

The put method on outer1 will not accept just any arbitrary instance of Inner: It must receive one derived from its own instance. ”Great“, you may say, ”but where is this useful?”. In the end, a powerful use of Path Dependent types is creating a tighter coupling between two related classes, in which the compiler can help us avoid mistakes.

Imagine, if you will, a (relatively simple) model of Airplane, Seat, and Passenger:

1
2
3
4
5
6
7
case class Passenger(firstName: String, lastName: String, middleInitial: Option[Char])

class Airplane(flightNumber: Long) {
  case class Seat(row: Int, seat: Char)

  def seatPassenger(passenger: Passenger, seat: Seat): Unit = ()
}

Given two separate Airplanes, it should be impossible to accidentally sit on the wrong plane!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
scala> val flt102 = new Airplane(102)
flt102: Airplane = Airplane@4b8d604b

scala> val flt506 = new Airplane(506)
flt506: Airplane = Airplane@4dc27487

scala> val kelland = Passenger("Mike", "Kelland", None)
kelland: Passenger = Passenger(Mike,Kelland,None)

scala> val mcadams = Passenger("Brendan", "McAdams", Some('W'))
mcadams: Passenger = Passenger(Brendan,McAdams,Some(W))

scala> val nash = Passenger("Michael", "Nash", None)
nash: Passenger = Passenger(Michael,Nash,None)

scala> val flt102Seat1A = new flt102.Seat(1, 'A')
flt102Seat1A: flt102.Seat = Seat(1,A)

scala> val flt506Seat21A = new flt506.Seat(21, 'A')
flt506Seat21A: flt506.Seat = Seat(21,A)

scala> val flt506Seat20F = new flt506.Seat(20, 'F')
flt506Seat20F: flt506.Seat = Seat(20,F)

If three members of the BoldRadius team are headed on journeys, but only two are boarding the same flight… what if we are so wrapped up in conversation that one of us tries boarding the wrong plane?

1
2
3
4
5
6
7
8
9
scala> flt506.seatPassenger(nash, flt506Seat20F)

scala> flt506.seatPassenger(mcadams, flt506Seat21A)

scala> flt506.seatPassenger(kelland, flt102Seat1A)
<console>:19: error: type mismatch;
 found   : flt102.Seat
 required: flt506.Seat
       flt506.seatPassenger(kelland, flt102Seat1A)

Excellent! The compiler catches that while Michael Nash and myself are headed out on the same flight, Mike Kelland isn’t. When Mike tries to board the wrong flight… the type system prevents it.

In short, we can use the Path Dependent Type logic to prevent crossing over into runtime bugs – if we’re smart about our domain design.

A Skeptic’s Guide to Scalaz’ Gateway Drugs: Part 2 - Options With Disjunction

| Comments

(This is Part 2 of a series of distillations of a presentation I’ve been giving for the last year, “A Skeptic’s Guide to scalaz’ Gateway Drugs”. It is meant to provide an introduction to the core functionality of scalaz that a developer might find most useful, without going off the deep end. Previous entries include Part 1 – Disjunctions)

Welcome back to the Skeptic’s Guide to scalaz. In the last part of this series, we introduced you to the power of scalaz Disjunctions—also known as \/—and how we can use them to indicate a return value of either an Error or a Success. As a reminder, convention dictates that Left—-\/—is an error, while Right—\/-—is success.

Hello? scalaz?

In this part, we’ll discuss interactions with Scala’s Option. Specifically, I want to discuss how to manage “stacks” of Option in for comprehensions, and how to use Disjunction to manage them.

A Skeptic’s Guide to Scalaz’ Gateway Drugs: Part 1 - Disjunctions

| Comments

(This is Part 1 of a series of distillations of a presentation I’ve been giving for the last year, “A Skeptic’s Guide to scalaz’ Gateway Drugs”. It is meant to provide an introduction to the core functionality of scalaz that a developer might find most useful, without going off the deep end.)

What is scalaz exactly? Well, at its core, scalaz is a functional programming library for Scala. It is intended to bring more functional programming concepts from languages like Haskell into Scala.

Until recently, I’ve looked at scalaz rather skeptically. As a self taught developer without any college or advanced mathematics training, I felt intimidated by what I saw. Long before I exited the ranks of rookie Scala programmer, I dabbled in Haskell a bit but left more confused than I started at.

So, tools like scalaz were a bit scary to me. Plus, “what’s wrong with the Scala standard library?”. As it turns out, a lot. Let’s look first at Scala’s Either, and where we can improve upon it.

Pickling Case Classes to Memcached With Scala

| Comments

Recently, I’ve been working on a rewrite of Sluggy Freelance - a friend’s site which I’ve worked on for about a decade now. Caching is a big part of keeping site cost down, and over the years I’ve come to trust Memcached. Fast, lightweight, and easy, Memcached has served me well over the years over several iterations of the site… from Perl, PHP, and Python.

Today, I’m rewriting the site in Scala with Scalatra and React.js. As a result, I’m discovering all sorts of new fun that I haven’t dealt with in Scala yet. One of these is using Memcached, and specifically serialising/deserialising Case Classes. With the combination of a good Memcached library - shade, in this case - and Scala Pickling*, I’ve found a powerful combination.

So far, I’m working with a datastructure representing navigation: the current book, chapter, and section as well as lists of others of those based on context. As a bonus… I’m actually serialising case classes that are fetched from Slick.

Distributing Akka Workloads - and Shutting Down Afterwards

| Comments

Recently, as part of my role with the Professional Services team at Typesafe, I have been working on site at a customer who is using a lot of Akka and Play. During this time, I’ve gotten a chance to solve some interesting problems and answer obscure questions… which for those who like chasing these kinds of puzzles issues (like myself) is a fantastic way to spend the day (and if this kind of thing sounds exciting to you, we’re aggressively hiring for this kind of work ;) )

One item in particular came up recently as we tried to create a cron-style job to do interval data processing – big blocks of input data would be separated into individual instructions for processing, using Akka 2.0.x. The developer I was working with found that, among other things, using only a single actor to process all of their data items was not particularly performant. Further, once we solved this problem we couldn’t figure out how to cleanly shut down Akka without interrupting any messages being processed. Fortunately, Akka offers simple answers to both of these problems… if you know where to look.