
2008/4/1, Bulat Ziganshin
Hello Simon,
Tuesday, April 1, 2008, 2:18:25 PM, you wrote:
How can one answer the question--why choose Haskell over Scheme?
1. static typing with type inference - imho, must-be for production code development. as many haskellers said, once compiler accept your program, you may be 95% sure that it contains no bugs. just try it!
2. lazy evaluation - reduces complexity of language. in particular, all control structures are usual functions while in scheme they are macros
3. great, terse syntax. actually, the best syntax among several dozens of languages i know
4. type classes machinery, together with type inference, means that code for dealing with complex data types (say, serialization) is generated on the fly and compiled right down to machine code
In my opinion, (1) and (3), as they are stated, are a bit dangerous if you want to convince a lisper: they represent two long standing religious wars. About (3), I see a trade-off: a rich syntax is great as long as we don't need macros. Thanks to lazy evaluation and monads, we rarely need macros in Haskell, even when writing DSLs. Sometimes, however, we do need macros (remember the arrow notation, whose need was at some time unforeseen). I think the only way we could compare the two is to make a s-expression syntax for Haskell, add macros to it (either hygienic, or with some kind of gensym), and (re)write some programs in both syntaxes. I bet it would be very difficult (if not impossible) to eliminate the trade-off. About (1), In most (if not all) dynamic vs static debate, the dynamic camp argues that the safety brought by a static type system comes at the price of lost flexibility. If we compare duck-typing and Hindley-Milner, they are right: heterogeneous collections are at best clumsy in Hindley-Milner, and overloading is near impossible. Thanks to some geniuses (could someone name them?), we have type classes and higher order types in Haskell (and even more). These two features eliminate most (if not all) need for a dynamic type system. About (4), I think type classes shines even more on simple and mundane stuff. No more clumsy "+" for ints and "+." for floats. No more passing around the "compare" fucntion. No more "should I return a Maybe type or throw an exception?" (monads can delay this question). No more <whatever I forgot>. For more impressive stuff, I think quick-check is a great example. About (2), I'm clueless. The consequences of lazy evaluation are so far-reaching I wouldn't dare entering the "Lazy vs Strict" debate. Loup