On static and dynamic typing, and corn tortillas

January 8, 2007 ⋅ 12 Comments »

Chalupa

The argument over static vs. dynamic typing in programming languages is one of those great geek debates that will never be resolved. Like Emacs vs. vi, Picard vs. Kirk, or chalupa vs. taco, it’s become a religious issue, with each side holding firm in their One True Belief.

Ok, I’m exaggerating a bit, but I think it’s fair to say that many people make an either/or choice with type systems. On the side of static typing, there are the formalists who dream of a day where programs can be proven to be correct; and on the dynamic side, there are the pragmatic hackers who want their language to be Agile. These two camps are fundamentally at odds, because there is very little grey area between their goals.

On the other hand, there are definitely some concrete benefits to be had from both approaches. For the graduate psychology class that I took at Carleton this fall, I decided to attempt an analysis of the pros and cons of static and dynamic typing from a usability perspective. Instead of the formalism vs. agility argument, I tackled it from a different point of view, asking “How can type systems make programming easier?”

I looked at several different aspects of type systems, and analyzed them in terms of the Cognitive Dimensions of Notations framework. One of the issues I addressed was mentioned in the post Why I Miss Static Typing.

If you’re interested, you can read the full paper. To give you a better idea of the general flavour, here is the abstract:

This paper uses the Cognitive Dimensions of Notations framework to analyze the usability aspects of static and dynamic type systems in programming languages. It presents seven problems, in the form of patterns, that are often encountered during programming. Solutions are presented for both static and dynamic type systems, and analyzed in terms of cognitive dimensions.


12 Comments:

  1. Greg Buchholz - January 9, 2007:

    You might really want to check out a language with a more modern type system. Something like Haskell, ML, Mercury, Omega, etc. A lot of the problems you see with static typing seem to be more related to Java's limitations. In you "array with failures" example, you'd probably use something like the Option type in ML, or the Maybe type and monad in Haskell. Or with your "passing functions as parameters", even C++ doesn't require you do declare the full signature of the function parameter. "template removeAppendix(Patient p, Func reportError)" will do.

  2. Greg Buchholz - January 9, 2007:

    Oops, that's

    template<class Func> removeAppendix(Patient p, Func reportError)

  3. Patrick - January 9, 2007:

    Thanks for the pointers. You're right, I should take a look at those languages. I have poked around with Haskell and OCaml, but only the tiniest bit.

    In your C++ example, is the type of the function still checked statically?

  4. Greg Buchholz - January 9, 2007:

    In your C++ example, is the type of the function still checked statically?

    Yes. I don't think I've ever seen a formal definition of duck typing, but C++ templates certainly allow you to treat anything that quacks and waddles as a duck, while still making sure your type mismatches are detected at compile time. Same goes for Haskell, Clean, etc.

  5. Patrick - January 10, 2007:

    I assume you're referring to type compatibility in those static type systems?

  6. Greg Buchholz - January 10, 2007:

    I assume you’re referring to type compatibility in those static type systems?

    If by "type compatibility" you mean types that can substitute for one another everywhere, then no. In Haskell, for example, you can create a function...

    double x = x+x
    

    ...which can be passed anything that understands the plus operator. So lets make lists of numbers understand "plus"...

    instance Num a => Num [a] where (+) = zipWith (+)
    

    ...now let's try it out at the REPL...

    $ ghci type_compat.hs 
       ___         ___ _
      / _ \ /\  /\/ __(_)
     / /_\// /_/ / /  | |      GHC Interactive, 6.6, for Haskell 98.
    / /_\\/ __  / /___| |      http://www.haskell.org/ghc/
    \____/\/ /_/\____/|_|      Type :? for help.
    
    Loading package base ... linking ... done.
    [1 of 1] Compiling Main          ( type_compat.hs, interpreted )
    
    Ok, modules loaded: Main.
    *Main> double 4.0
    8.0
    *Main> double 42
    84
    *Main> double [1,2,3]
    [2,4,6]
    *Main>
    

    ...so you can use floating point numbers and lists of integers in some of the same places, but I don't think they'd be called compatible types.

  7. Patrick - January 10, 2007:

    What I meant by type compatibility is that the compiler is able to determine that a type has a specific interface (in your example, that it understands the + operator) without any sort of explicit declaration.

    In short, your example is exactly what I meant. Thanks.

  8. Greg Buchholz - January 11, 2007:

    Here's the similar thing in C++ which will work with lists of doubles, lists of lists of ints, etc...

    #include<iostream>
    #include<list>
    #include<iterator>
    
    using namespace std;
    
    template<class T> T p(T a, T b){ return a+b; }
    template<class T> list<T> operator+(list<T> a, list<T> b)
    {
       list<T> out;
       transform(a.begin(),a.end(),b.begin(),back_inserter(out),p<T>);
       return out;
    }
    
    int main(int argc, char* argv[])
    {
        double x[] = { 1.0, 2.0, 3.0};
        double y[] = {10.0,11.0,12.0};
        list<double> a(x,x+sizeof(x)/sizeof(double));
        list<double> b(y,y+sizeof(y)/sizeof(double));
        list<double> c;
    
        c = a+b;
    
        copy(c.begin(),c.end(),ostream_iterator<double>(cout, "\n"));
    
        return 0;
    }
    

  9. Greg Buchholz - January 11, 2007:

    Here's a better operator+ for that example...

    template T operator+(T a, T b)
    {
       T out;
       transform(a.begin(),a.end(),b.begin(),back_inserter(out),
                 p);
       return out;
    }
    
    

  10. Greg Buchholz - January 11, 2007:

    Here's a better operator+ for that example (now with angle brackets)...

    template<class T> T operator+(T a, T b)
    {
       T out;
       transform(a.begin(),a.end(),b.begin(),back_inserter(out),
                 p<typename T::value_type>);
       return out;
    }
    
    

  11. Patrick - January 11, 2007:

    Ok, but in those examples, what happens if you instanitate a list, where MyClass doesn't implement operator+?

  12. Greg Buchholz - January 11, 2007:

    You get a compiler error.