Home » Blog » The type wheel turns again

The type wheel turns again

It’s slightly spooky when you’re discussing a topic and evidence for (or against) your position seems to spontaneously appear. The fashion for strong versus weak type systems seems to change on a cycle of about a decade. It might be turning again.

On Monday I was talking with a student who’s doing a project using node.js, looking at using it as the basis for doing elastic concurrent programs. It’s the sort of project that could underpin some kinds of low-end cloud computing, letting designers use JavaScript end to end.

The discussion turned to type systems, and how Javascript’s very weak view of types makes things more difficult for his project, as he will have to constantly protect against having the wrong methods called. On the other hand, it makes other things easier by letting him create proxies and other structures freely. The question is then whether strongly-typed languages are preferable to weakly-typed ones.

In a strongly-typed language, every denotable value has a type, the language ensures that all uses of those values are type-correct and generates a type error if not. A strongly statically-typed language does this purely at compile-time, and it’s generally recognised by those who advocate these approaches that it’s preferable to catch as many errors as possible as early as possible. It’s also recognised that this isn’t always possible (think Java class loaders), and so some run-time structures are also needed — but these can be provided so as to catch problems as early as possible (when code is loaded). (See Dobson and Matthews. Ionic types. In ECOOP 2000 – object-oriented programming, pages 296–312. Elisa Bertoni (ed). Volume 1850 of LNCS. Springer-Verlag. 2000.)

For some people, static typing feels too rigid: the compile will often prevent things that the programmer “knows” to be possible. In this case a looser type regime is often preferred. Strong dynamic typing checks at every operation to make sure that the values being manipulated are type-correct; weak dynamic typing does fewer checks, often only detecting problems very late; untyped or monotyped languages do few or no checks and will apply any operation to any piece of data at the programmer’s instruction.

I tend to fall into the strong static typing camp — which is slightly ironic, given that I’m currently working on untyped extensible virtual machines. Programmers’ beliefs that they know better than the type-checker are often erroneous, the more so as code gets more complicated.

The fashion for type systems seems to follow a cycle. People are using a language with strong typing when a new kind of programming comes along, often driven by some new technology. The strong types are restrictive for this new domain (having been designed for a different world) so programmers invent or re-discover languages with dynamic typing that allow them to write the code they need to write without the difficulties of fighting a type system. In large-scale systems, programmers also like being able to evolve the data structures gradually, without having to update every user. (Doing so in the presence of strong types often doesn’t work, although with care it’s possible.) This leads to a widespread belief that type-checking is unnecessary, difficult, for losers, etc, and that dynamic languages are the only way to go.

Then, as programs get bigger and more complicated, problems start to emerge. Typically these revolve around different parts of the system not agreeing on the exact data representation, so everyone has to check the data they receive because the language offers no guarantees that it’ll be correct. (This is the down-side of being able to evolve the representation piecemeal.)  Such checks rapidly become untenable, and so programmers start thinking about whether there are automated mechanisms to improve checking — and re-discover strong type systems.

Having been discussing this in the context of Javascript, I then stumbled across TypeScript, a Javascript extension that allows type annotations. These aren’t exactly a strong type system — they’re optional, for a start — but definitely mark a change in the way Javascript would be used, as a system with defined type structure rather than as a type free-for-all. Since Javascript occurs in a lot of systems these days — on the front-ends, but also increasingly server-side — this is a welcome departure. I find it hard to believe that large, long-lived component-based systems can be built in a dependable fashion using only a dynamic approach to typing. It relies too much on programmers’ willingness and ability to check everything, every time.

Actually there are strong arguments for the need for non-static run-time checks, most notably in distributed systems when you can’t be sure the data you receive will be type-correct even if the compiler that generated the code thinks it is, since you generally don’t have complete control over all the components and their evolutions. But this isn’t an argument against strong typing in general: it still helps, even if there are small holes. Instead one perhaps needs to check types at the component boundaries so that, once admitted, you have confidence in their type-correctness. This in turn places demands on the transport protocols to be self-describing in terms of their payloads’ types, and doing so supports other constructs (like type-driven computation) for free without sacrificing the benefits of the strong checks. Having some dynamism (and room for run-time failure) within a generally static seems like a decent compromise.


Leave a comment