Tuesday, July 16, 2019

Scalazzi safe Scala subset (Principles 2, Scalaz Files)

Scalaz is designed for programmers building type-safe, functional programs. If you program like this, you can start to see very deep properties of your functions by only reading their types; in other words, types become documentation. This also lets you see how you can combine your functions in more ways, with greater confidence that the combination will actually make sense.

But Scala, the language, contains many unsafe features that get in the way of this method of thinking about your programs. “Scalazzi” means that you are avoiding or banning these features from your Scala codebase, thus restoring your ability to use types to discover those properties.

  1. null
  2. exceptions
  3. Type-casing (isInstanceOf)
  4. Type-casting (asInstanceOf)
  5. Side-effects
  6. equals/toString/hashCode
  7. notify/wait
  8. classOf/.getClass
  9. General recursion

Here’s an example of how you might use these rules to reduce your testing requirements.

Suppose that you have this very simple function to return the greater Int.

def maximum(x: Int, y: Int): Int = if (x >= y) x else y

(I encourage you to imagine that this is harder than this example; after all, aren’t your own programs more complicated?) This type signature says that any Int can be returned; we must test to verify that this isn’t happening.

Instead of writing a test, we can use parametricity to check that either x or y is returned, but nothing else, at compile time instead of test time.

def maximum[N <: Int](x: N, y: N): N = // • • •

I can read from this type that only x or y can be returned. With some practice, you’ll start to see more complex facts arising from types as well.

Unfortunately, Scala has many “features” that let you break this safety. These features aren’t useful for type-safe functional programs, so we simply declare them verboten.

Scalaz expects you to follow Scalazzi rules, but is also packed with features to help you follow them. For example, if you are calling map on a List and feel like your lambda needs to perform some side effect, it’s time to look into Scalaz’s Traverse typeclass.

No comments: