When working out the design for a new system, is it better to start with a statically-typed language (like Haskell), or a dynamically-typed language (like Ruby)?
Arguments I can think of:
With a static language, you can quickly create a specification and scope for what the program will do. With a dynamic language, you can quickly create a working demo to present to the customer for review.
With a dynamic language, you often avoid having to rearrange data structures and refactor code when you change your design. With a static language, you can define types before implementation, keeping the code to maintain very small.
With a static language, you have to figure out in advance what your program will do. With a dynamic language, you can start writing code, and let the design grow organically. As Paul Graham says in Hackers and Painters:
A programming language is for thinking of programs, not for expressing programs you've already thought of.
With a static language, the compiler can help identify many types of bugs. With a dynamic language, you can begin testing and finding bugs sooner.
Static and dynamic typing both have advantages and disadvantages as far as prototyping is concerned. However, they both seem to me like equally valid approaches. Based on your experiences, which one is ultimately better?
Notes
Prototyping in natural language
A third type of language to consider: natural language. Instead of prototyping in code, one can prototype in writing. The customer can then read your documentation and critique your design early on, but cannot toy around with a working demo. If well-written, the documentation can make implementation in any language straightforward. Caveats:
The documentation may be tedious to read through, and difficult to digest without being able to see it. I speculate that a customer would rather experiment with something that works rather than read a wall of text (and images).
Prototyping an application in English rather than in type definitions is more verbose and less concrete.
Haskell types are descriptive
Note that types are particularly descriptive in Haskell, more so than in many static languages like C++ and Java. For example, suppose I have a function with this type signature in Haskell:
foo :: forall a. [a] -> a
A function that, for any type a, takes a list of items of type a and returns a value of type a.
Even without knowing the function's name, I know for a fact that:
It does not perform input/output or modify any values (well, unless it uses unsafePerformIO incorrectly), because Haskell is purely functional.
It cannot treat the items as, say, integers, because it has to support any type.
It has to use the input list (that, or throw an exception or go into an infinite loop). Otherwise, where would it get a value of type
afrom?
Therefore, the only thing this function could possibly do (other than fail) is extract an item out of the input list and return it. Although I still do not know which item it will use, [a] -> a tells me just about everything else.
