I recently picked up a project in OCaml that I had begun last summer and never finished. I have to say, compared to my day-to-day tools (mostly Java these days, Python before), OCaml is a breath of fresh air. For instance, today I did a refactoring where I replaced a type that was simply an alias to string with a proper abstract data type. Fixing the code was simply a matter of compiling, going to the file/line number in the error message, fix and repeat. Algebraic data types (sometimes called discriminated unions) are great for properly separating the logic of a data structure instead of sticking everything into one big class.
I highly recommend you give it a try. By the way, although we hear about OCaml less often than other languages, it is still used in many well known places such as Facebook (for pfff and Hack), Microsoft (SLAM, a verification tool for drivers), and Airbus (they use the ASTRÉE static verification tool which is written in OCaml).
Scala came at the problem from the wrong direction. F# started with the functional pieces of ML/OCaml and added the 'OO' stuff in record types resulting in a simple and powerful language. Scala seems to have started with the 'OO' stuff and then has kept on adding and adding and adding.
> I'm unsure how OCaml counts as "functional". It doesn't even have typeclasses, let alone higher-kinded types.
Erm, what? Functional languages are those which implement as much as possible using functions, rather than adding language primitives (eg. if/then/else, looping, mutable state, etc.). If anything, typeclasses make a language less functional, since they're a language primitive which could be implemented with functions instead (by passing records explicitly).
Lambda Calculus doesn't have typeclasses or higher-kinded types, does that mean it doesn't count as "functional"? Hell, even Joy is a purely-functional language and it can't even call functions!
Type systems are a completely orthogonal concept to functional style; they're a way of embedding a formal logic into a programming language. It just-so-happens that many logics make heavy use of implication (a -> b), and that corresponds to functions. It's possible to give a rich type system to, for example, Prolog or assembly, but the logical operators would be quite unfamiliar.
In Scala typeclass is not a language primitive, it's just an idiom that can be easily expressed in the language. Whereas programming in the typeclass style with F# is difficult to say the least, basically requiring Greenspunning.
"Functional" means many things to many people, but it's the term a lot of people use when talking about the recent rise of languages like Haskell, Scala, F# and OCaml - much of which rise is, IMO, attributable to their type systems. Whatever "it" is that these languages have (and sure, it might be more accurate to talk about "languages providing ADTs and controlled sequencing of effects" or some such), I think it's fair to say that OCaml/F# have less of it in this area, because their type systems don't allow you to express higher-kinded types.
F# may have its advantages, but you're definitely missing out on some of the "functional language renaissance" - because whatever the terminology, at least some of that renaissance is about the value of powerful type systems.
> "Functional" means many things to many people, but it's the term a lot of people use when talking about the recent rise of languages like Haskell, Scala, F# and OCaml - much of which rise is, IMO, attributable to their type systems.
These are new languages in the functional paradigm but functional programming isn't itself a new concept, and strong static typing has never been a prerequisite in order to be "functional". The first functional language, Lisp, was dynamic, and to this day no commonly used Lisp has been statically typed out-of-the-box. Erlang and the array languages (APL, J, etc.) are other examples of dynamically typed functional languages.
You can say that functional languages are more likely to have strong type systems than other languages, but it's totally disingenuous to claim that languages are somehow "less functional" because they lack typeclasses and higher-kinded types.
To be precise most array languages are not functional, although they do support "function-level programming" - the distinction is not clear to me just yet, but I hope to improve. :)
The K language, which presumably incorporates parts of Scheme, is a notable exception to this.
Like the original FP/FL languages, J supports function-level programming via its tacit programming features (note that function-level programming is not the same as functional programming).
As I said, it's unclear to me what the difference is, but that's what I based my previous comment on.
That sentence only means to say that J supports function-level programming, which itself is different from functional programming. The very same Wikipedia page also calls J a functional language -- the fact that it supports function-level programming doesn't contradict the fact that it also supports functional programming.
The meanings of words shift, particularly in a fast-moving field like ours. But like I said, which word use isn't really important. I care more that:
Something is going on in the languages I mentioned - and from my perspective, distinctly isn't going on with any Lisp (including Dylan or Clojure), isn't going on with the array languages, and mostly isn't going on with Erlang. So it's not a functional language thing by your definition of a functional language
Whatever that something is, it involves powerful type systems
F# and OCaml therefore have less of it than Haskell and Scala (though more of it than languages outside those four list).
> Something is going on in the languages I mentioned - and from my perspective, distinctly isn't going on with any Lisp (including Dylan or Clojure), isn't going on with the array languages, and mostly isn't going on with Erlang. So it's not a functional language thing by your definition of a functional language
Um, no. Lisp and Erlang are still functional. They have always been and will always be functional. The definition of that word has not changed. You seem to want to redefine "functional" to make Haskell the end-all and be-all of functional languages, but that's just not how it works.
The whole point of the post you were replying to is that arguing about what the word "functional" means is beside the point. To many people there is a categorisation of languages to which Haskell and Scala more strongly conform than Lisp and Erlang. What that category is called is of secondary importance to the discussion.
Semantic arguments are tiresome, and I wish more people would focus on the content of the discussion, instead of arguing about how it might better have been conveyed. Sometimes people misunderstand the commonly accepted meanings of terms, and it's worth correcting them. But if people start arguing about terminology, then it's better to just define terms and move on, since there's clearly not a consensus worth teaching anyone.
> If anything, typeclasses make a language less functional, since they're a language primitive which could be implemented with functions instead (by passing records explicitly)
I'm not exactly sure what you're thinking of here, but if you try to turn a typeclass into a dictionary of its methods, you'll need a dictionary for each instantiation of type variables in the typeclass. And then it still won't be as type-safe as Haskell, because nothing stops a programmer from swapping in random dictionaries. This is the flaw in the Scala implementation of type-classes.
It comes from my knowledge of functional programming and the problems that come from trying to do this stuff by passing dictionaries. I'm not a Scala programmer, so maybe I've missed some subtleties, but I doubt it. Here's Edward Kmett:
"Since you can pass any dictionary anywhere to any implicit you can't rely on the canonicity of anything. If you make a Map or Set using an ordering, you can't be sure you'll get the same ordering back when you come to do a lookup later. This means you can't safely do hedge unions/merges in their containers. It also means that much of scalaz is lying to itself and hoping you'll pass back the same dictionary every time."
You get the same issue with Ocaml's implementation of polymorphic tree-based maps, where you lose type-safety. This is why you don't want to pass dictionaries for this stuff, but instead want to use modules and functors, which allow you to emulate existential types, higher-order kinding and higher-rank polymorphism.
It would be probably important to note that F# module and object systems are completely different from OCaml as they are designed to support interop with the rest of .NET.
On the other hand, OCaml is able to express typeclasses with it's module system.
The key missing feature -- module functors -- was thought by many to be impossible to represent correctly within the CLR's metadata. I had an idea last year about how they could be implemented within the CLR's type system; the proof-of-concept code is gross, but keep in mind it's only meant to prove that F# could eventually implement module functors: https://github.com/jack-pappas/experimental-functors
As a haskeller, I've heard some disconcerting things about OCaml.
Namely, the standard lib is more or less made just to be able to compile itself, and that the standard lib is not pure, which makes developers go to alternate implementations to do the job in a way that is expected.
Please do correct me if what I've heard is wrong.
My only indirect experience with OCaml is the Opa language compiler--so all I've seen is that it is a language favored for implementing languages.
The stdlib that ships with the compiler is indeed minimal, though it is used for things other than the compiler. It can be used for other projects, but you probably want something more full-featured. Core, and the more minimal and portable Core_kernel (https://github.com/janestreet/core_kernel) is a full-featured alternative that is growing in popularity, and is what the book I worked on (Real World OCaml, http://realworldocaml.org) is based on.
OCaml (and most of both the stdlib and Core) default to immutable data structures, but OCaml has good support for programming imperatively, to its credit, in my view.
FWIW: Core doesn't work with Windows (the Real World OCaml book does state this upfront) so you need either an OSX or Linux machine to work with Core, and so you can't work through the book with a Windows machine. Something to be aware of.
For what it's worth, the world has changed since then: Core_kernel (which is the highly portable bits of Core, which is most of it) works on Windows just fine. Indeed, WODI, which is the best windows package manager for OCaml right now, ships with it.
Hi, Yaron! I was recently looking into using Core for one of my projects, but have so far failed to find any good, clear, complete documentation or how-to guide. Is there anything like that available online? I guess I could read the Real World OCaml book to learn parts of it, but I already know OCaml...
I've heard that Jane Street uses their own extensions to the language. Also, how does one deal with the development of OCaml being largely done in French?
Jane Street makes use of OCaml's built-in metaprogramming facility, camlp4. While these are in some sense "our own extensions", they're wholly shareable without using a hacked version of the compiler, and just because we build our code using these syntax extensions, doesn't mean that users of our libraries need to do the same. You can use Core_kernel, for example, without using our syntax extensions.
The French thing is a non-issue. The compiler is written and documented in English, and all the main contributors are fluent English speakers, and the mailing lists are almost entirely in English.
> Also, how does one deal with the development of OCaml being largely done in French?
OCaml is developed by french people, I've never heard of it being done in french (aside from interpersonal banter I guess). The french version of the official site doesn't even work correctly (when you click on the "manual" link you get the english manual)
I think, you are misinformed. While the standard library is not huge, it is quite ok. Then, OCaml is steadily gaining strength with Opam and Jane Street's libraries, which become de-facto standard.
Personally, I see OCaml as C++ done right (minus pointers), if you need pointers, use Rust.
The default string type is terrible, the default file input output introduces space leaks and has terrible performance. The default numerical hierachy, (Num a) in particular, is nothing mathematicians tend to study (it would be much more sensible to define Ring a, for example). It overemphasizes lists and instead of attempting to define polymorphic functions that give access to a wide range of containers, pollutes the global name space with list specific functions, even though lists are rarely the right choice.
There are several alternative Prelude implementations, but as far as I am aware none of them address all of these issues. Since most of the other libraries depend on the default Prelude, especially the type class hierarchy it establishes, the none breaking changes they could make are very limited. For a discussion of one of those proposals see http://www.yesodweb.com/blog/2012/08/classy-prelude-good-bad....
Things could be worse, take Scala for example.
There are lots of high quality libraries, but no major effort to replace the Prelude's privileged position in the language. So it it kind of a minefield to find the correct module/function for your needs.
Haskell Platform is a great standard set of imports, but it is only for the commonest libs, beyond that you have again the problem of sorting out excellent libs from some student's throwaway homework project with the same name.
Thanks for this comment. I always wondered if I was the only one who felt that way, or if I was just missing the point when I found these things weird.
Another Haskeller here. I strongly recommend you take a second look at OCaml. I think it has some fantastic features that Haskell doesn't:
Modules. They are great for solving major code organisation problems and I really hope Haskell will get a module system soon ("Backpack" paper). Type classes are great for things like Monad and Num since you are likely to use many different Monads or Nums in the same chunk of code. But consider what happens if you want to support both ByteString and Text in your library (let's say a parser library). You may end up with a type class constraint like ListLike and your code will be littered with 'ListLike .. =>'. But when you're parsing some data later on it will be either ByteString or Text. So I'd fix my choice of ListLike at module instantiation time and make the constraint go away. If I need both (e.g. I'm reading some data from a socket and some of it is Text and some of it is ByteString) then I'm just going to instantiate two modules, one for each. To me this is a much cleaner solution.
Named/optional function parameters. They solve a bunch of minor but incredibly annoying problems. A simple example: for (aka flip map); It is not in Prelude and whenever it comes up there are plenty of people who are opposed for one reason or another. In OCaml (Core library) it doesn't matter because map takes the function by named parameter so List.map ~f:(fun x -> x + 1) [1;2;3] works fine and so does List.map [1;2;3] (fun x -> moderately long, perhaps few lines long function). Both cases are important for readability. Another example: in Haskell I've been working with APIs where functions have 20+ positional parameters (yeah, it's terrible design but that's out of my hands). If they were named and some of them optional (most of them really are optional) then the code would be a fraction of what it is.
OCaml is quick to compile. I've been looking at Eliom web framework recently and rebuilding a website takes seconds; compare that to yesod which takes forever and spins all the cores on my laptop which eats my battery in no time.
OCaml code tends to be quite straightforward: from my experience it is longer than Haskell equivalent, uses less abstractions but at the same time it is conceptually simple.
Typed printf. (yeah, there are 'solutions' in Haskell but it's a typed printf out of the box!)
Polymorphic variants. Can be used to bring information to the level of types. Compare
Also see OCaml's tyxml package which provides typed html5. Yeah, the types look rather crazy in some places but that's a small price to pay for rooting out invalid HTML.
This does make me want to take a look OCaml seriously.
I'd mostly use it in a web server context. Though I have no clue where to really get started in that.
Yesod actually was one of the reasons that pushed me to learning Haskell (though I arguably never got much done in Yesod since it felt like its pragmatisms didn't match up with mine.)
OCaml has compiler level support for format strings. "%d" and friends get parsed into a GADT at compile time and printf "%d" has type int -> unit
In Haskell PrintfType => type-class magic is used to make printf accept a variable number of arguments. However, the types of those arguments are not checked against the format string (since the format string is just a string). Hence the error happens at runtime and Haskell's printf is effectively untyped.
It is not very hard to implement printf that takes a GADT and and has a proper type (e.g. Int -> String) and there are libraries that do something along these lines (see formatting library on Hackage; there's also a template-haskell based solution that uses a quasi-quoter [fmt|%d\n|]). But I do prefer the elegance of c-style format strings.
Besides OCaml has this out of the box and in standard library while Haskell printf is dangerous and should be avoided. Even C++ is better -- I've seen compilers/linters throwing warnings at me when arguments didn't match the format string. Printing to stdout/stderr shouldn't be hard and shouldn't be something one needs third-party libraries to do nicely. Hence I've put it on the list.
What made me give up on Haskell was all the libraries had native linux bindings. It was hell reusing code if you're developing on windows (and I've heard this is true on macs, too). Does OCaml have this issue?
Unix support is definitely better than Windows. That said, the core language and base libraries are pretty portable. Here's one nice retrospective on a move from Python to OCaml for a program that needed portability to Windows as a fundamental concern.
> Probably the biggest problem on Windows is that OPAM, the package manager, doesn't work there. That will come eventually, though
Wodi [1] is a reasonable choice until OPAM starts supporting Windows. It includes many of the interesting/useful libraries (including, importantly, batteries [2] and core [3])
I think it really depends on the application domain. A lot of Haskell (for example most of the web frameworks) doesn't have the problem you mentioned - but GUIs and numerics systems probably do. I would guess the same may be true for OCaml. If I were developing on Windows though I would probably lean towards F# over OCaml though...Visual Studio is an amazing IDE.
Java's "write once, run anywhere" comes with a lot of costs that many programming language designers aren't willing to pay. It's not just about the JVM (which by itself prevents Java from running on some devices), it requires Java to adopt a "lowest-common-denominator" approach when it comes to supporting platform-specific features, and often go to great lengths to appear to support features that are easy on one platform but hard on others. As an example, look how long it took Java to even support something as basic as PIDs thanks to cross-platform compatibility concerns. Given that .NET has plenty of excellent languages in its own right, I suspect it will be a long time before we see another language willing to restrict itself as heavily as Java has in order to attain this utopic ideal.
(Personally, I don't really think it's worth it--many libraries that need to get stuff done in Java end up using JNA anyway, negating this supposed advantage. But it's certainly much better about it than ostensibly cross-platform languages like Ruby are).
Ocaml has a bytecode compiler and a native code compiler; any library written in OCaml can be compiled to run-anywhere bytecode, though I'm not sure how many libraries are really just wrappers around native GNU/Linux libraries.
The biggest change is OPAM, http://opam.ocaml.org/, a top-notch package management system that makes installing OCaml packages much easier.
Shameless plug: there's also a newish O'Reilly book, Real World OCaml http://realworldocaml.org, which I think is a big help in learning the language.
Oh, and there's OCaml Labs, a new lab at Cambridge University that's dedicated to improving the language.
And of course the compiler is constantly making progress. The upcoming 4.02 release is a pretty fun one, which I documented here: https://blogs.janestreet.com/ocaml-4-02-everything-else/ And before that, changes like GADTs and first-class modules landed, which have been quite useful extensions.
Really, it's a very active and fun community these days. The language is getting better quite quickly, but mostly in conservative and tasteful ways. The people in charge of the core language have been doing a great job, and the community infrastructure (things like OPAM) have been making big strides as well.
It looks like the ecosystem is fairly small. Another thing that is off-putting (unless I'm missing something) is that OPAM packages have no online docs per default, something that is standard with Haskell packages, for instance, and is definitely a big help.
I've seen a ton of great improvements in tooling/ecosystem.
- OPAM was already mentioned.
- The OCaml to JS compiler has matured and gained a lot of use. Interestingly, I suspect that it can also be used to achieve different types of parallelism than the types that the stock OCaml compilers provide.
https://github.com/ocsigen/js_of_ocaml
VimBox (shameless plug) uses Merlin and is configured to provide "intellisense" style completion (as you type) like Visual Studio.
https://github.com/jordwalke/VimBox
- utop is perhaps the best top level REPL that I've ever seen.
https://github.com/diml/utop
(edit: Regarding utop: Normally I dread using a REPL for a statically typed language, but utop actually makes the top level fun and interactive. I actually look forward to using it!)
I think it's progressing pretty well, but not yet as polished as something like Python or Ruby.
I've tried it a few times through the years. Most recently I grabbed a kindle version of "real world ocaml" a couple months ago, and started to work through it. The fact there's a recent book in English made it easier to get into than the previous times I've looked at it, and a good sign of progress, IMO.
Unfortunately, after a couple weeks a new version of ocaml came out, and some packaged from opam were updated, and something about it broke everything for me and stopped me in my tracks. I'm pretty sure it's a problem waiting for changes to trickle through to osx, but I don't really know. I spun up a linux vm, and everything worked great, so it seems osx specific.
I found that using homebrew's OCaml and OPAM really painful, and made things not work very well. Moving to OPAM directly and letting it manage OCaml for me has made things work brilliantly on OS X, to the point where I really wish I could use OCaml at work; it's a seriously nice language.
I've often seen OCaml compared to F#; as someone who knows Haskell and Rust (among others), which is better to learn? I'm not really a Windows guy, which makes me think OCaml, but I've seen that Xamarin now works with F#, which is appealing to my inner app developer.
I prefer F#, but only so because it has decent visual studio tooling and .net interop. F# power tools' refactoring is great, and its syntax coloring is very good as well. http://puu.sh/a1vM5/c735f3d319.png (i swear this looks a lot nicer on the washed out screen i program with)
The interop with .net libs is helpful too - but i've found that if there's anything that's really hurting F#, it's all the OOP tacked onto it to make the .net interop work. Decent tradeoff if you ask me, but it's cringeworthy to see people using F# like an oop language when the oop only appears to be there for the interop magic to work.
F# is essentially OCaml.NET, so knowledge of either will be very transferable to the other. F# can interface with C# types, but it feels cumbersome at times. Idiomatic F# is very similar to idiomatic OCaml.
Comparing OCaml and F# is about like comparing Java and C#. The MS languages started out very similar to the others, but made much larger strides. F# has changed their syntax to be lighter, with something similar to Haskell's offside rule. They added workflows which are monads but not quite as nice as Haskell's.
One big point I would give to F# is tooling. Having a real IDE for OCaml would be nice. When I was writing OCaml I used Emacs with ocamlspotter.
The other big F# feature is library support. OCaml has pretty good libraries but F# can leverage the whole .NET framework. This would be noticeable in areas like GUIs.
I imagine that not using Microsoft F# would negate the benefits of F# over OCaml.
To be honest, go with either. For most people the benefits come from the simple/common/old features. Once you get used to dealing with the compiler, you'll likely fall in love with ML.
I considered picking up OCaml at one point, but got scared off by the global interpreter lock. Can an experienced OCaml dev tell me when this would really become an issue, and certain cases where it wouldn't make a difference?
My experience has been building parallel and distributed programs using multiple runtime instances that communicate via message passing. There are libraries that help automate this, link our own Async_parallel (https://blogs.janestreet.com/async-parallel/). One advantage of this approach is that it scales beyond a single box.
There is work going on at OCaml Labs on a parallel runtime. I suspect it will be useful, but in the end, message passing is I think a better idiom than shared memory threads for parallel programming. When the true parallel runtime lands, I'm not sure that we'll actually use it much for running truly parallel threads.
> I suspect it will be useful, but in the end, message passing is I think a better idiom than shared memory threads for parallel programming.
It really depends on the problem you are working with. You wouldn't want to make a high-performance HTTP server this way. Especially if you get to copy 2MB of POST data every time.
For an HTTP server you should use Async or LWT, which are lightweight concurrency libraries. You can handle quite high levels of concurrency with either one. My impression is that people building highly parallel HTTP servers do quite well with collections of processes with a load-balancer in front, but it's not my area of expertise.
Async and LWT give you lightweight concurrency mechanisms. Libraries like Async.RPC give you lightweight remote invocation, and Async_parallel gives you simple mechanisms for spinning up multiple physical processes and communicating between them.
Don't get me wrong: OTP by all accounts has richer support for this kind of stuff. I think OCaml is a better language for many purposes, but OTP is a great runtime and set of libraries whose equal is not yet found in any other language as far as I can tell.
I tried OCaml once. It was to figure out the algorithm Yaron Minsky (author of linked article) used for his orbital simulator, Planets. I only learned enough to port the code over to JS, and quickly forgot it. Coming from a procedural programming background, the learning curve was too steep for OCaml.
I highly recommend you give it a try. By the way, although we hear about OCaml less often than other languages, it is still used in many well known places such as Facebook (for pfff and Hack), Microsoft (SLAM, a verification tool for drivers), and Airbus (they use the ASTRÉE static verification tool which is written in OCaml).