Me on Xoltar on Static Typing

Bryn Keller (a.k.a. Xoltar) takes on Bruce Eckel’s comments about Python and static typing, and does a pretty good job at poking all the holes in Eckel’s arguments while remaining objective. Worth a read, especially if you’re wondering what all the hoopla is about Haskell and O’Caml’s type systems.

My Comments

Bryn comments toward the end of his article about how duck typing can lead to ‘dangerous’ situations. He uses the example of a method named draw, which has different semantics for the Gunslinger class (where draw means ‘Bang!’) vs a Artist class (where draw means ‘paint’). While it’s possible to have such name clashes with different semantics, in reality I don’t think it’s a big problem: certainly one not worth spending a few paragraphs on in an article. (When would this situation ever crop up, for example?)

He points out that in the Nice language, you can write a class, and make them part of the interface later. In his words: “We also got additional power in the bargain, because now we can selectively bless any class we like into the Speaker interface, without including classes we don’t want - we can ensure that our Artist doesn’t end up in a gunfight by mistake!”. In languages such as Java or C++, you must declare that a class implements an interface when you write the class: you cannot write a class and declare later that it implements the interface. It is very cool to program in a language which enables you to separate the code you write, from declaring how that code is used as part of your whole system design. Some other examples of this feature in other languages are:

  • Haskell, which enables you to declare a type class to capture common functionality provided by different functions. So, you could write a Haskell module which provides a new Hashtable data type, and another Haskell module to provide a new balanced tree data type. You can then later write a type class to capture operations common to such colletion/aggregate types, by writing a new type class that declare type signatures for functions such as inserting objects into the collection, or retrieving objects from the collection. Note that you could have completely different interfaces to the hashtable/tree classes with completely different type signatures: the type class performs the ‘glue’ code necessary to provide one clean, consistent interface to both of them. (Plus, the very small glue code required to do that will be optimised away by any optimising Haskell compiler, such as GHC.) This is the same idea as Nice’s separation of code declaration vs interface declaration, though type classes are a far more powerful and generic concept.
  • Objective-C’s categories, which enable you to add new methods to existing classes. You don’t like it how the NSFileHandle class doesn’t have a method to create a new temporary file and return you a file descriptor for it? No problem, just add your own method to do that to the class — no subclassing necessary. Categories are possibly the greatest thing I miss about Objective-C when I use any other language (Haskell included: it would be really cool to be able to extend type classes by adding new methods to them!). C# has a similar feature named partial types, although it’s nowhere near as elegant as categories. Perl 6 takes this idea even further than Objective-C does: it differentiates between open classes, which can have methods added to them, and closed classes, which can’t. The clever bit is that all classes are open by default, but any users of that class will close the class unless it’s specifically declared open. This is really smart because it means that you can have the same flexibility that open classes give you, but you gain all the optimisation opportunities that come with closed classes, such as performing static dispatch rather than dynamic dispatch on a function call, which opens up a whole new set of optimisations that weren’t previously possible, such as inlining.

One of the points of Bryn’s article seems to be that static typing detects different errors from unit tests: while this is true, I’d phrase this a different way. One benefit of unit testing is that it helps you develop your code faster because unit tests enable your code to be more robust as you develop it, saving you from hunting down those stupid bugs later on. Modern static type systems give you different test coverage, and I think they speed up your development even more, because they often pick up a lot more errors than unit tests do. If you’re a Perl programmer, the use strict; pragma that Perl has basically turns on static type checking. Think about how many bugs you’ve found thanks to its warnings and errors, and imagine how much of a nightmare it’d be if you didn’t have that facility at all. Now think about extending Perl’s simple type system (which is limited to only type checking of scalars/arrays/hashes), so that types are pervasive in your program design that enable far better coverage by the type checker, and you’ll hopefully have some idea of what I’m talking about.

He remarks right at the end of his article that “We need both strong testing and strong typing” — I think he means static typing, not strong typing, considering that was what his entire article was about :). Mind you, static and strong typing seems to be confused quite easily: even Guido van Rossum confuses strong typing with static typing. I personally find it a bit worrying that the designer of such a popular (and great!) language gets it wrong, but hey, nobody’s perfect.

Bryn, I think, doesn’t point out the biggest benefit of modern static typing systems: it saves you time because so often, when that anal type checker finally does let your program compile, it just works a really surprisingly large amount of the time. (This is closely related to the increase in productivity that I discussed above, but it’s not quite the same thing.) It’s downright unnerving just how many times your program performs correctly: one thread on the cvs-ghc mailing list gives an anecdote, where most of the Glasgow Haskell Compiler back-end was ripped out and re-written (14000 lines of code!), and the PowerPC code generator worked first-go. I’m yet to nail down whether this phenomenon is only due to the advanced type systems alone, or whether it’s a combination of the powerful type system and a (purely?) functional programming style; I suspect it’s the combination of the two. Programs are much easier to reason about when state changes are made explicit.

blog comments powered by Disqus