Computer Assisted Programming

Submitted by Greg Buchholz
on August 25, 2005 - 1:03pm

I don't know what it is, but I seem to be running into a lot of people lately who are against static typing. And most of theses people who dismiss static typing have a seemingly narrow view of what it enables. I assume this comes from lack of experience with good statically typed languages (here I'm thinking a language like Haskell or and ML dialect with a "modern" type system. Something with polymorphic types and type inference, like the Hindley-Milner system (circa 1970's)). What I'd like to do is present another view that many people are apparently unaware of.

If you want you manifesto against static typing to be taken seriously,
here's at least one scenario I think you'd be wise to address: using
the type system to perform "Computer Assisted Programming". This is what
I mean. We know that both static and dynamic languages can be Turing
complete, so we can solve any computable problem in either domain. And
I think that (regardless of type system) most people would agree that
there is a spectrum of program complexity, ranging from trivial, on
though moderate, then hard to understand, ending up eventually at
utterly incomprehensible. (Two people might disagree where to draw the
line between simple and obtuse, but they'll still agree on the spectrum
idea).

Now let's take the set of hard and very hard to understand programs.
Is it conceivable that a sub-set of these programs are hard for humans
to deal with because they require lots of tedious bookkeeping to make
sure that everything works together correctly? Shouldn't we leave the
tedious bookkeeping to the machines and let people handle the high level
concepts? Couldn't an automated bookkeeping system allow for
greater programmer productivity and shift some of those problems
from the hard-to-very-hard domain down into the medium-to-hard domain?

Here's an analogy. Think of the stealth fighter. A conscious decision was made to sacrifice aerodynamic performance in order to achieve a low radar signature. In fact, unlike regular aircraft, the stealth fighter is completely unstable. It requires constant readjustment of its control surfaces to keep it from immediately tumbling out of control. And the adjustments needed are too complicated for the human nervous system to make. But the task can be handled easily with a computer. The pilot makes the high level decision of which direction the plane should point, and the electronic machine makes it happen.

But back to static typing. For a concrete example of a situation with very complicated types that is immensely improved by static typing, I'd take a look at monadic parser combinators like in the Parsec library. It has been my experience that the types involved are complex enough that trying to debug an implementation in a dynamic setting is so difficult that you'd probably be better off trying a different approach. But in a statically typed setting, they work great, since any errors you make are caught at the source of the problem, not when you get a runtime error trying to apply an anonymous closure to an invalid argument after its been passed around through several different functions.

If you say that those situations aren't that widespread, or that trying to use these more complicated programs is bad practice under any circumstance, then fine, make that argument. I personally would be genuinely interested in what you have to say, and we all might learn something from the dialog. But if you're going to trot out the same tired examples to shoot down static typing, be prepared for a yawn and a "seems like you're preaching to the choir" reaction.

(Boilerplate Disclaimer: Let's just get a few standard things out of the way...

  • Yes, I agree that it is perfectly possible to create real, working
    systems in dynamic languages.
  • If you want to argue against static typing, shouldn't you argue against one of the best example languages, instead of the weaker ones? Otherwise you might be accused of attacking a straw man.
  • Complaints about not being able to write programs like you are use to sounds suspiciously like complaints made by procedural programmers towards object oriented programming. In other words, it seems like that's mostly a problem of not being familiar enough with the style. If you are constantly "fighting" the type system, it may indicate that you are not using it in the proper manner. Maybe you should think of it as a totally different programming paradigm (type oriented if you will).
  • If you claim you never (or rarely) make type errors, maybe that's because you're not taking enough risks and pushing the limits? (i.e. you're not using sophisticated enough algorithms and/or data structures). Most economists would agree that in an imperfect world, the optimal number of bankruptcies is not zero. No bankruptcies implies that credit is too tight, and entrepreneurs aren't being allowed to take enough risks (since the successes outweigh the costs of the inevitable losses for the economy as a whole).
  • Finally, just for the record, you can (if you so desire) shift your Haskell type errors to run time. And you can have your compile-time meta-programming and runtime eval cake in Haskell and eat it too.

nice article

Kevin Barnes (not verified)
on
August 25, 2005 - 2:23pm

Great article, and I agree with most of the points your making. I'm not a static-typing opponent, to me these are all trade-offs as per your stealth fighter analogy (actually all modern fighters have this problem). There are things that can be done in dynamically typed languages to provide stronger contract guarantees, but these also require work.

I am not really knowledgable about Haskell, so while I mention it I don't pretend to be an expert or even a qualified amateur. I'll need to spend some time getting to know it better the next time I have a little program to write. If you could get static-type-safety without the loss of meta-programming elements (or truly and completely destroying your syntax) then two thumbs up from me.

To be fair to dynamic-type advocates it's probably worth acknowledging that most people are more familiar with the very poor examples of Java and C# (given the dominant role they are playing in programming today) and if you have to trade off static typing to get something more powerful than Java, then the decision isn't really about statc vs dynamic (that's just spin) it's about the languages in question.

Yes!

on
August 25, 2005 - 2:42pm

To be fair to dynamic-type advocates it's probably worth acknowledging that most people are more familiar with the very poor examples of Java and C# (given the dominant role they are playing in programming today) and if you have to trade off static typing to get something more powerful than Java, then the decision isn't really about statc vs dynamic (that's just spin) it's about the languages in question.

I agree 100%. And the word "spin" sums up the situation nicely. I guess its just a pet peeve of mine when people state that static typing in general is the problem, when they're really talking about one particular instance. BTW, for the curious, I don't hate dynamic languages either. In fact, I love Perl and Scheme as well as Haskell. (Talk about a dichotomy!)

Sticking with the Analogy

Darius (not verified)
on
August 25, 2005 - 4:41pm

What if there is a flaw found in the controls while in flight (a light bulb? simple but critical)? Could one fix it in flight?

What if a new enemy strategy is discovered while in mid flight that can only be recognized by satellite, reacted to, and piloted by the speed of a computer. Can the stealth fighter be reconfigured in flight to avoid certain destruction by the new enemy strategy, if the adjustment to the new remote-controlled-maneuver passes all onboard unit test?

What if the enemy implements “ground bounce radar” in mid flight so that all the fields and methods labeled “hidden” or “now in stealth” need to be relabeled as “formerly hidden” and “formerly in stealth” while in flight?

Are unit tests for all systems deployed with the stealth fighter?

Today’s stealth fighters probably assume almost all parameters are known in advanced.

Business systems need to react faster and morph more completely than stealth fighters in the business battle arena because there are more factors (other entire markets, long term natural resource variances, short term weather, human employee health, new sci/tech discoveries, new laws, new disruptive innovation, etc.) and more people looking for more advantages and weaknesses non-stop 24x7.

Perhaps computerizing an entire war from beginning to all possible ends, with thousands of people at a thousand different controls, might be a better analogy. We probably need to keep reevaluating fundamental assumptions every day this day in age.

Sure

on
August 25, 2005 - 5:52pm

Plugging Haskell In...

Extension languages enable users to expand the functionality of an application without touching its source code. Commonly, these languages are dynamically typed languages, such as Lisp, Python, or domain-specific languages, which support runtime plugins via dynamic loading of components. We show that Haskell can be comfortably used as a statically typed extension language, and that it can support type-safe dynamic loading of plugins using dynamic types. Moreover, we discuss how plugin support is especially useful to applications where Haskell is used as an embedded domain-specific language (EDSL). We explain how to realise type-safe plugins using dynamic types, runtime compilation, and dynamic linking, exploiting infrastructure provided by the Glasgow Haskell Compiler. We demonstrate the practicability of our approach with several applications that serve as running examples.

Helping improve my content

on
August 26, 2005 - 12:28pm

I'm afraid I maybe wasn't as clear as I could have been. I was making a number of assertions (some more implicit than others), some of which you apparently don't agree with. I'll try a more explicit list and maybe you could identify which ones you agree/disagree with, so I can better present my ideas to someone who doesn't necessarily share my particular set of biases and preconceived notions. Or for that matter, anyone who disagrees with my thesis is encouraged to mark the statements below with agree/disagree...

  1. There exist programs which resist human understanding.
  2. There exist programs with types so complicated, that they are hard to understand.
  3. There exist programs with complicated types and other, simpler programs can analyze these (the complicated) programs to be sure that the types are used in a consistent way.
  4. The programs in item 3 above exist, but knowing their types are used consistently doesn't make them easier to understand.
  5. The programs in item 3 above exist, but their number is insignificant, and should be ignored.
  6. The programs in item 3 above exist, but it is dangerous (because of their inherent complexity) to try and use them.
  7. The programs in item 3 above exist, but they don't have any use.
  8. What?!? Types are only a shorthand notation for whatever particular machine representation a value has (Doubles are 64 bits long, etc) and have no value in understanding how programs work.
  9. other?

What seems missing in your argument

Scott David Daniels (not verified)
on
August 26, 2005 - 5:35pm

This is the statement closest to my take:
The programs in item 3 above exist, but knowing their types are used consistently doesn't make them easier to understand.

My position is that type errors are the least troublesome errors that I encounter in programs under development. Type checking helps a bit when first writing a program, but those are far from the worst issues I encounter. Type safety advocates often over-state the protections it provides; "thinkos" and off-by-one issues are the nastiest, and those are not addressed by type systems that I know about.

Thanks

on
August 26, 2005 - 6:27pm

Thanks for you comment. Hearing what others have to say about the situation is valuable.

One more real quick question.

My position is that type errors are the least troublesome errors that I encounter in programs under development.

Ignoring the practical for a moment, can you imagine a contrived program where that's not the case? Is it theoretically impossible to construct a function that calculates something trivial (adding one to its argument, for instance), but does so in an overly complicated manner and has a bunch of crazy types it uses as a result? Say this is for an obfuscated programming contest (see The Evolution of a Programmer). Would knowing about the types not help at all? Or not help enough. Maybe I should have phrased it as, "The programs in item 3 above exist, but knowing their types are used consistently doesn't make them easy enough to understand to make it worthwhile." Would that be a better way of expressing your feelings?

update: Whoops, I also wanted to ask this, "Do you think it is possible for me to create a program with a type error in it that would be trivial to find in a static language, but really hard to track down in a dynamic language?" And if I could, wouldn't that put you in catergory 5, 6, or 7 from above?

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.