Regarding type classes, I personally like Haskell's approach more. I haven't used Scala, so I'm assuming that objects there behave the same as modules in OCaml (at least in practice for this particular purpose). Essentially, Haskell makes the right compromise: the most common case (having one instance per type) is easy while the less common case (explicitly specifying the instance) is less easy. The core difference is this: when you want to use a different "instance" in OCaml, you just pass in a different module; in Haskell, you have to create a new type.
Happily, creating a new type is easy, especially with newtype deriving which lets you bring instances you don't want to change over to your new type for free. This has some advantages: the instance is now encoded in the type, so that you cannot mix different ones by accident. This is useful because it's quite easy to have code that depends on, for example, a consistent compare function in different places on the same type. This also lets the choice of implementation be implicit at the call site, so you only have to specify the instance once rather than repeatedly in different places.
I think there is also a good case for type classes not being reified as modules or dictionaries or objects or what have you: they essentially exist exclusively at the type level. That is, the instances are a property of each type, not part of a module or anything like that. This also makes the syntax for types clearer: the => acts as implication and the type class acts as a predicate on the type.
In summary: type classes are more restrictive than first-class modules, but this is a good compromise. You can get the same effect with newtype, with the added bonus of having the difference reflected in the type system.
I'm afraid I have not managed to make my thoughts on type classes too clear. I've been thinking about that particular design trade-off (type classes vs first-class modules) and writing this has probably helped me get my thoughts together far more than it will help any readers :P. Maybe I'll write a blog post about it--I've been meaning to start a blog for a while now...
Some other thoughts: I think laziness is a good thing because you trade performance for simplicity and expressiveness. It's easier to add strictness to a lazy language than vice-versa. But I essentially use Haskell where others would use something like Python, so its relative performance is well beyond satisfactory even with plenty of space leaks :P.
As far as developer tools go, Scala has Ensime [1] and Haskell has Scion [2] but I've used neither. OCaml has TypeRex [3], which I have used and is pretty cool. Assuming that Ensime and Scion are similar to TypeRex, they're certainly good enough. You never have to leave Emacs :).
Coincidentally, OCaml has some of the advantages the author found in Scala while being more like Haskell. I would certainly consider at least playing around with it a bit--it's a very nice language. I still prefer Haskell, but not by too large a margin.
"I think there is also a good case for type classes not being reified as
modules or dictionaries or objects or what have you: they essentially
exist exclusively at the type level. That is, the instances are a property
of each type, not part of a module or anything like that. This also makes
the syntax for types clearer: the => acts as implication and the type
class acts as a predicate on the type."
Yes, redefinable instances of type classes feels a bit like monkey patching.
"Some other thoughts: I think laziness is a good thing because you trade
performance for simplicity and expressiveness."
Lazy evaluation allows a more declarative way of programming.
While Scala's objects may be comparable to OCaml's modules, implicits add something on top of that to bring it much closer to type classes. As the name implies you do not have to specify the instance at each call site. The implicits mechanism can automatically resolve an instance based on the type. If you want a different one you can pass a different instance manually, however.
(shameless plug) If you're into alpha code, you should check out my hie [1] (haskell-in-emacs). When I wrote it, ghc-mod and scion only supported show-type-at-point when the file typechecks, which is more or less useless when refactoring. Pretty sure that is still the case.
hie actually parses the file (using a modified version of haskell-src-exts to support more extensions), and gives show-type-at-point, goto definition, and auto complete with inline haddock documentation. Its autocomplete is context sensitive--for instance, if you type "import " you will only see modules. It also works somewhat incrementally and on-the-fly. YMMV, and it isn't documented well, but I use it every day and haven't had any problems.
If you want to try it out, you'll probably need Emacs 24. It might work on Emacs 23. Use hie-fetch.py to fetch the source for all of the packages you have installed, and "hie-hackage.py cachedir" to pre-cache your libs. First time import of Prelude will be slow, but afterwards should be instantaneous.
If you have problems the code is pretty self-explanatory IMO, but feel free to e-mail me (addr in the .el file) with comments and concerns.
I think the "final words" are the definition of 'obsequious'. Say something of real substance, and commit to it:
"Haskell and Scala are both very powerful and practical programming languages, but with different strengths and weaknesses. Neither language is perfect and I think there is room for improvements in both. I will definitely continue to use both of them, at least until something better shows up. Some new interesting ones on my radar are Rust, ATS and Idris."
The only disagreement I would have is that while the JVM is a great runtime, I would love the ability to compile to native code to get faster start up times.
Also I know its a preference thing, but I like curly braces. It makes an old C programmer feel more at home.
Happily you can use curly braces in Haskell if you really want to. You have the choice between:
do something 10
b <- somethingElse
something b
and
do {
something 10;
b <- somethingElse;
something b
}
I've only ever seen the latter style very rarely though. I think it's also good for generating code so that you don't have to worry about whitespace and lining your generated code up properly.
A comparison between two languages only makes sense if the purpose of each language is the same, e.g. if the purpose of both Scala and Haskell is to enable programmers to build stuff easily, or if it was to build performant code, or whatever.
But if the purposes are different, then comparing Scala and Haskell is like apples and oranges. If Scala's purpose is, say, to introduce Java programmers to Haskell, then a comparison would even be part of the purpose of Scala. Moving Java programmers to Haskell could very well be Odersky's real motive behind building and marketing Scala. He could actually be a hero of the programming ecosystem instead of a former academic who started a company to milk a software product he got grad CS students to build for free. This talk about exploring functional/object fusion could be bogus, a cover story for showing programmers how easy typed functional can be, and prompting them to consider a full move to Haskell.
In fact, Clojure looks like a similar case of introducing something to Java programmers. What with Clojure for Javascript coming out, and now even a C-target version, Clojure's looking more and more like an underhanded way to move Java programmers to Lisp. Surely Hickey's finishing the job, started back in 1995 when Java "moved C++ programmers half way to Lisp".
12 comments
[ 1.6 ms ] story [ 362 ms ] threadRegarding type classes, I personally like Haskell's approach more. I haven't used Scala, so I'm assuming that objects there behave the same as modules in OCaml (at least in practice for this particular purpose). Essentially, Haskell makes the right compromise: the most common case (having one instance per type) is easy while the less common case (explicitly specifying the instance) is less easy. The core difference is this: when you want to use a different "instance" in OCaml, you just pass in a different module; in Haskell, you have to create a new type.
Happily, creating a new type is easy, especially with newtype deriving which lets you bring instances you don't want to change over to your new type for free. This has some advantages: the instance is now encoded in the type, so that you cannot mix different ones by accident. This is useful because it's quite easy to have code that depends on, for example, a consistent compare function in different places on the same type. This also lets the choice of implementation be implicit at the call site, so you only have to specify the instance once rather than repeatedly in different places.
I think there is also a good case for type classes not being reified as modules or dictionaries or objects or what have you: they essentially exist exclusively at the type level. That is, the instances are a property of each type, not part of a module or anything like that. This also makes the syntax for types clearer: the => acts as implication and the type class acts as a predicate on the type.
In summary: type classes are more restrictive than first-class modules, but this is a good compromise. You can get the same effect with newtype, with the added bonus of having the difference reflected in the type system.
I'm afraid I have not managed to make my thoughts on type classes too clear. I've been thinking about that particular design trade-off (type classes vs first-class modules) and writing this has probably helped me get my thoughts together far more than it will help any readers :P. Maybe I'll write a blog post about it--I've been meaning to start a blog for a while now...
Some other thoughts: I think laziness is a good thing because you trade performance for simplicity and expressiveness. It's easier to add strictness to a lazy language than vice-versa. But I essentially use Haskell where others would use something like Python, so its relative performance is well beyond satisfactory even with plenty of space leaks :P.
As far as developer tools go, Scala has Ensime [1] and Haskell has Scion [2] but I've used neither. OCaml has TypeRex [3], which I have used and is pretty cool. Assuming that Ensime and Scion are similar to TypeRex, they're certainly good enough. You never have to leave Emacs :).
[1]: https://github.com/aemoncannon/ensime/
[2]: http://code.google.com/p/scion-lib/
[3]: http://typerex.org/
Coincidentally, OCaml has some of the advantages the author found in Scala while being more like Haskell. I would certainly consider at least playing around with it a bit--it's a very nice language. I still prefer Haskell, but not by too large a margin.
Yes, redefinable instances of type classes feels a bit like monkey patching.
"Some other thoughts: I think laziness is a good thing because you trade performance for simplicity and expressiveness."
Lazy evaluation allows a more declarative way of programming.
hie actually parses the file (using a modified version of haskell-src-exts to support more extensions), and gives show-type-at-point, goto definition, and auto complete with inline haddock documentation. Its autocomplete is context sensitive--for instance, if you type "import " you will only see modules. It also works somewhat incrementally and on-the-fly. YMMV, and it isn't documented well, but I use it every day and haven't had any problems.
If you want to try it out, you'll probably need Emacs 24. It might work on Emacs 23. Use hie-fetch.py to fetch the source for all of the packages you have installed, and "hie-hackage.py cachedir" to pre-cache your libs. First time import of Prelude will be slow, but afterwards should be instantaneous.
If you have problems the code is pretty self-explanatory IMO, but feel free to e-mail me (addr in the .el file) with comments and concerns.
[1]: https://github.com/monsanto/hie
"Haskell and Scala are both very powerful and practical programming languages, but with different strengths and weaknesses. Neither language is perfect and I think there is room for improvements in both. I will definitely continue to use both of them, at least until something better shows up. Some new interesting ones on my radar are Rust, ATS and Idris."
Because someone isn't a fanboy and isn't just stupidly commiting himself to one thing, than he's obsequious? Well, I would call this a smart person.
Also I know its a preference thing, but I like curly braces. It makes an old C programmer feel more at home.
Aonix and JET are two of them.
Sadly, GCJ is dead even though is still part of GCC.
But if the purposes are different, then comparing Scala and Haskell is like apples and oranges. If Scala's purpose is, say, to introduce Java programmers to Haskell, then a comparison would even be part of the purpose of Scala. Moving Java programmers to Haskell could very well be Odersky's real motive behind building and marketing Scala. He could actually be a hero of the programming ecosystem instead of a former academic who started a company to milk a software product he got grad CS students to build for free. This talk about exploring functional/object fusion could be bogus, a cover story for showing programmers how easy typed functional can be, and prompting them to consider a full move to Haskell.
In fact, Clojure looks like a similar case of introducing something to Java programmers. What with Clojure for Javascript coming out, and now even a C-target version, Clojure's looking more and more like an underhanded way to move Java programmers to Lisp. Surely Hickey's finishing the job, started back in 1995 when Java "moved C++ programmers half way to Lisp".