It turns out that sophisticated functional programming essentially stresses that good modularity and good purity are both killer features and techniques and they should be in heavy use all of the time. In OCaml you'll have an easy time expressing the exact modularity concerns you find important, but will struggle a bit to manage purity explicitly. In Haskell you'll find it beautiful to express pure and typed-effectful computation as much as needed, but will struggle a bit with expressing modularity as you'd like.
Haskell also has the whole typeclass system which is really, really interesting and valuable for many kinds of expressiveness. It's sort of an oddball feature, but interesting to see the impact of.
Personally, I find strict purity more important than expressive modularity. But if anyone could really put them together in a way that worked it'd be great. I'm not so sure such a language exists today, though.
There is Ur, which has both ML-style modules and Haskell-style type classes. It's also pure and strict. And it has advanced type-level programming features and record types. There's a lot to like.
There are a few problems with it, though. It's mostly a one-man project. The compiler is immense, complex and almost entirely devoid of documentation (it's pretty amazing actually, like 1 comment per 1000 lines or so), so contributing is hard. It's very difficult, if not impossible, to use the language for anything but web development: there's no way that I know to execute a program directly, rather than as a sub-program of the ur/web framework. The standard library is tiny and doesn't even include `print`. But even with those warts it has enough good things about it that it's worth checking out.
Honestly, Ur is completely ingenious but there remains an enormous challenge getting it away from being entirely Adam's project. It's completely web-only right now (although Ur is supposedly a more generalized language) as the only compiler is Ur/Web.
Agreed to all of that. I've tried to get into it several times, but I have almost no interest in web development. I'd really like to use it just as a language. It seems like it should be possible to decouple it, but it seems like the only way that will happen is if Adam gets more people in on it. And that's not likely to happen with the scanty documentation and completely impenetrable compiler code. :(
Haskell is more expressive and has a much more powerful type system, but it's probably harder to reason about performance.
OCaml's biggest issue (note: I may be out of date on this, since I haven't heavily used it since the late 2000s) is the GIL. This probably limits your ability to use it for multithreaded programming, but it can compile down to extremely fast single-threaded executables.
http://eprints.eemcs.utwente.nl/1077/02/book.pdf
I'm not sure I agree with all of the conventions, but it's interesting to see a deliberately functional approach applied to C code.
(Not that I actually do. Maybe someday).
Ocaml is more practical in a hard to explain way. Much more predictable in terms of it's memory and cpu use with non-lazy default evaluation, and I found much better performing on general code.
OCaml does not have generic ways of doing monadic stuff (do notation or generic >>=), which means in practice that monadic code looks like "fun1 x >>= (fun r -> )" which is kind of awkward. It also doesn't have typeclasses (yet).
However, one thing you're unlikely to find in OCaml and which is unfortunately not uncommon in Haskell is functions with a long list of positional parameters (since you have named arguments) or different versions of the same function with a "_" suffix, depending on various defaults (since you have named arguments). It makes a tremendous difference of readability when dealing with complex code.
Also, interface files (.mli), while a bit of a pain to maintain at times, give a very clear idea of what interface a given module exposes.
All in all, I find OCaml code much easier to read, not to mention less "clever" than equivalent Haskell code.
Can you give an example, I'm interested in seeing what you mean but having trouble figuring out what an example would look like.
There’s a strong community around Haskell, with a decent library ecosystem and high-quality implementations, and learning it will make it easy to pick up F# or OCaml—the reverse is not necessarily true.
F# is a decent choice if you want to write functional code in .NET land, but Visual Studio and MonoDevelop support for F# aren’t as good as for C#.
OCaml is a good language, but I would recommend against it. Like F#, it has some syntactic and semantic conveniences that Haskell lacks. However, the community is small, there are relatively few libraries, and the runtime falls down when you need to do anything with large arrays or floating-point math.
I haven't had a chance to use OCaml or F# yet, what syntactic and semantic conveniences are you talking about?
OCaml's strictness makes some things easier to reason about. Haskell is a nicer language and has more momentum.
- the way you access records (which also means it's not going to clutter your namespace)
- named arguments
- default values
- not an OCaml-the-language property, but there is much less of a race in the OCaml ecosystem to write the shortest variable name possible and accumulate the most ASCII operators
Also, the great module system, with easy abstract types or "public" types with private constructors. By contrast, having to export accessors (if using a lens library) is embarrassing.
The short variable names in Haskell follow the convention that the more polymorphic your variable is, the shorter its name should be. Eg in
map f (x:xs) = f x : xs; map _ [] = []
f, x and xs are very polymorphic, so there's really no better longer name there.
And you could easily write:
map func (item:items)When I'm writing map, parametricity literally ensures that I cannot care about the element of the list. Giving their priority with any thought toward the name is actually taking the focus off the list structure where it belongs.
The trick is that once you're exposed to short names at the right places you realize that there are relatively few times that variables are meaningful as much more than function-wiring notation. Especially in pure code!
As soon as you add in mutability this all goes out the window really fast. Subsequently, you see "meaningful" variable names all the time in IO or ST code.
map fn (head:tail) = (fn head):(map fn tail)
map _ [] = []A few weeks into learning Haskell, reading x:xs will become second nature, so much so that "head" and "tail" become noise. (Also, "head" and "tail" are function names in the Prelude, but I'll assume you meant to write "hd" and "tl" or something like that).
(Also, "head" and "tail" are function names in the Prelude, but I'll assume you meant to write "hd" and "tl" or something like that).
No, I overlooked that. Writing "hd" and "tl" would be opposite to my point! I think that "head:tail" is much more readable and much more informative than "x:xs".