12 ms·
Why We Use OCaml
- mackwic 11y agoI don't know if it brings anything new on the table. Also, I am not convinced that Ocaml is state-of-the-art in term of development productivity, relase-management, debugging, etc. Anything any non-trivial project could want. Language features is not the only thing we need. Yes, the OCaml tooling has really improved recently, and the OCaml workflow has been more and more smoother. Still. I wont recommend it for a business. So, if the original author read this, could you answer these questions about how do you ship products with Ocaml: - How do you do Quality Assurance ? (anything from unit-testing, integration testing, functional testing, etc. I guess you have to do it a lot to check that Gmail didn't break its integration). Testing in isolation has its share of challenges in Ocaml. - How do you manage your builds and releases ? Private Opam repositories ? Directly shipped to Google ? Do you have beta/staging channels ? - And last but not least, what have been the pain points so far and have you been able to fix them or do you just work with it ? (it happens with any tech stack, but it's good to know what the trade-off are) I am very curious how this could work at "entreprise-scale" and I would be glad to have some real world examples of ocaml in production.
- tegeek 11y agoIf you've a look at F#, you get all of the things you said plus OCamel syntax (without functors etc.).
- kyllo 11y agoWhat do you mean by "without functors?" F# doesn't have a way to define a `map` function that is generalizable to arbitrary data types?
- pdpi 11y agoOCaml functors are not the same thing as Haskell functors — in OCaml they refer to mappings from modules to modules. https://realworldocaml.org/v1/en/html/functors.html https://realworldocaml.org/v1/en/html/functors.html
- ufo 11y ago"Functor" might just be the most overloaded term in computer programming... Just of the top of my head it has totally different meanings in Ocaml, Haskell and C++.
- kyllo 11y agoThey're not totally different between OCaml and Haskell. They're based on the same concept from Category Theory: a mapping of objects and morphisms from one category to another. It's just that Haskell functors are at the type level and OCaml's functors are at the module level. Apparently F# has support for neither style of functor--it doesn't have parametric modules and it also doesn't have typeclasses. So in F# `map` is defined independently for each type: Set.map : ('a -> 'b) -> 'a Set -> 'b Set Seq.map : ('a -> 'b) -> 'a seq -> 'b seq List.map : ('a -> 'b) -> 'a list -> 'b list Array.map : ('a -> 'b) -> 'a [] -> 'b []
- mackwic 11y agoF# is an excellent technology, and inspired some of the recent Ocaml developments (we still look at ActivePattern with envy). I saw some pieces of F# in the FinTech here and there, I think Microsoft could do a better job at marketing it because it really has great potential in the .Net ecosystem.
- mbrock 11y agoI'm not sure why these things require state-of-the-art technology. Like, testing is basically just checking a bunch of if statements. You can use fancy frameworks that color your tests red and green, but other than that kind of thing, what's the actual problem? Why do you say testing in isolation is particularly challenging with OCaml? It's been years since I used OCaml and I don't know anything about OPAM so I'm also interested in the answers. Did you try to use OCaml and run into a bunch of difficult problems?
- mackwic 11y ago> Did you try to use OCaml and run into a bunch of difficult problems? Yeah, I am a long date contributor and user of ocaml for little projects (mostly compilers and AIs). But not professionally. > It's been years since I used OCaml and I don't know anything about OPAM so I'm also interested in the answers. Opam is Bundler done right. It manages ocaml toolchains and packages dependencies. It's easy to pin a specific version or publish your own. A setup oasis + ocamlbuild + $editor could go quite far. After that, it will depend of how you works and what you are developing. > Like, testing is basically just checking a bunch of if statements. You can use fancy frameworks that color your tests red and green, but other than that kind of thing, what's the actual problem? Why do you say testing in isolation is particularly challenging with OCaml? That is a very interesting question that deserve a blog post on its own. But I don't have the time nor the patience to do so, so let it be the HN comment. > Like, testing is basically just checking a bunch of if statements. Wrong ! There's multiple kind of "if statements to test"; -1- I want to test that `my_inner_fibo(0, 1) == 1`. This is unit test. Basically a transcript of the technical specifications into assertions. This is the easiest test, the most verbose, but it's also the kind that test the least. -2- I want to test that `UserModule.retrieve_orders(user, command)` makes the good calls. This is integration testing in white box, which test that the API contracts between you inner interfaces are respected (which is also part of the technical specifications). I don't find it very useful but it's better than nothing when you can't do more. -3- I want to test that, with a given state `user`, and `command`, when I call `UserModule.retrieve_orders(user, command)` I get exactly this object. This is integration testing in black box. This is useful to find errors in inner logic a group of modules (but you don't know immediately what gone wrong). As the call stack could be very large (and so the scope of what you are testing), you want to reduce the moving parts and replace some of the modules with trivial mocks. Integration testing in a black box test a lot of things and is very useful to find bugs. -4- I want to test that a call to `$./my-binary ctl command --flag=true` have a specific behavior. Could also be a network request to a server, a message to a deamon, a click on a GUI... Anything exterior to the program. Here we test the behavior. This is what the user will use, that's why it's functional testing. This could break often (in the case of a GUI) or not (in the case of a CLI binary). You should always do functional testing if you respect you users a little. All these kinds of testing have different requirements, and some need a perfectly controlled state to be created. The issue is not in the conditional testing, but in the setup this perfect controlled state, which sometimes need to make the code believe it use the good module, but you gave him a stubbed one which does trivial work, or signal you when something happens. I don't know any simple way to spy on functions without using the MirageOS design which heavily use Functor injunction. It's quite an academic way of doing it.
- melling 11y agoWhat part of the tooling has improved recently? Is there a particular IDE that's now better to use, for example?
- Drup 11y agoThe IDE situation is now excellent (thanks to merlin[1]) and OPAM, the OCaml Package Manager, is the best package manager I have ever used. The remaining pain point, as far as tooling goes, is the debugging situation, but steady progress has been made and it should receive very large improvements in the next OCaml version or so. [1]: https://github.com/the-lambda-church/merlin https://github.com/the-lambda-church/merlin
- stewbrew 11y agoWith respect to opam: is it usable under windows yet?
- avsm 11y agoNot in a released version, but there's very active work in trunk to make it work natively: https://github.com/ocaml/opam/compare/master...dra27:windows-build A recent demo I saw a few weeks ago had everything running under Cygwin and building native Windows executables...
- nv-vn 11y agoKind of. It's a bit awkward to get it running on Windows, but somehow (by accident) I managed to do a fully functioning installation on Cygwin. That said, many of the packages have still not been ported to Windows, so my recommendation is to set up a headless VM of some GNU/Linux distro and SSH into it.
- mercurial 11y agoWell, I'm not sure I would go as far as "excellent". There is no "OCAML IDE", there is vim/emacs + tools. You can hack an IDE-like workflow by way of inotify, but if you want the "works-out-the-box" experience, that's not going to happen. As you mention, debugging is lacking, and more generally Merlin can't do much in the way of refactoring. If you're fine with, eg, hacking Python in VIM, you'll be pleasantly surprised by the OCAML situation. If you live in an integrated IDE, there will be some adaptation.
- rwmj 11y agoI'll tell you how we do these things in the libguestfs/virt-tools project [1]. The project is written in a mix of C, Perl and OCaml. Mainly C is used for the low-level/library bits, and OCaml is used for the higher-level tools. - QA: We have some unit tests, but mainly we use a huge test suite that does end to end testing of tools. It uses automake's test framework, so it works across all the languages in the project. - Builds and releases: We use autotools and tarballs. It's automated using a thing called 'goaljobs' which is like a generalized make. - The pain points for us all derive from autotools itself, which is both crap and better than all the other build systems[2]. It is at least well understood. I'd also say the killer advantages of OCaml for me are: Easy calling into C, and compiles to a native binary. [1] http://libguestfs.org http://libguestfs.org https://github.com/libguestfs/libguestfs https://github.com/libguestfs/libguestfs [2] I use the term "build system" in a rather narrow sense of something that (a) runs on Linux (b) lets the end user download a tarball and (c) builds using ./configure && make
- mackwic 11y agoThanks for your detailed answer and congrats for successfully maintaining libguestfs. > I'd also say the killer advantages of OCaml for me are: Easy calling into C, and compiles to a native binary. Very true. And Ocamlbuild makes wonders.
- Drup 11y agoI'm always very amused when people say OCaml can't work at "enterprise scale" (let me snort a bit on that one, considering the scale of some open source projects) given the amount of evidences of the contrary[1] [1]: http://ocaml.org/learn/companies.html http://ocaml.org/learn/companies.html To answer one of your question. Yes, we have testing frameworks, both for unit[2] (inline[3]) testing and property testing[4]. As for the rest, it's not OCaml specific at all. :) [2]: http://ounit.forge.ocamlcore.org/ http://ounit.forge.ocamlcore.org/ [3]: https://github.com/vincent-hugot/iTeML https://github.com/vincent-hugot/iTeML [4]: https://github.com/c-cube/qcheck/ https://github.com/c-cube/qcheck/
- mackwic 11y ago> I'm always very amused when people say OCaml can't work at "enterprise scale" Yeah, you will notice that quotes that show you shouldn't take it too literally. ;) (also I have no doubt that Ocaml can work in a business. I just saw no one speak about it appart Jane Street, so I am curious) What I was meaning that "a team with a hierarchical organization, not-ony-geniuses, and more than 4 people". Few of the serious Ocaml projects (if any) fall in this category, which is common for all businesses. About the testing tooling, I am well aware of the state of these technologies. I even contributed to some of them. Sorry but it's light. It doesn't cover all the spectrum of what you'll want to test in a product. Let's take your (excellent) libs and see: - OUnit: unit tests - QCheck: unit tests - iTeML: unit tests Where is integration and functional testing ? Unit Testing only test a very strict subset of the "does this work as intended" question. I recommend you to see how some projects do their testing. For example any classic Rails project. You could be surprised. Some open questions I struggle myself to answer correctly: - Mocking modules without having a build mess with oasis - Managing the model in a sane way - Integration testing is an horror And many more that I can't recall now.
- vog 11y agoNot sure about the other issues, but I believe this one is easily solved: > Mocking modules without having a build mess with oasis OCaml has parametrized modules (aka "functors"), which provide a very clean solution, compared to mocking whole modules anyway. As a side note, I usually see mocking being used to test badly structured code. Refactoring that is usually a benefit for testing as well as a benefit for the code itself.
- edwintorok 11y agoHere is how I handle this at my company. LibreS3 is a product written in pure OCaml [1], using as a backend a cluster running Skylable SX (written in C)[2]: - QA: unit tests written using oUnit, and integration tests by using linked Docker containers. - builds/releases: opam + packages written for Debian and Fedora based distributions. The packages provided on our website are built inside Docker just like all the other packages. Internal beta packages are uploaded to a separate volume/bucket and served via LibreS3 itself. - Pain points: building a package compliant with packaging policy is more complicated because I usually need newer versions, or OCaml libraries that are not yet packaged. I planned to use opam to generate templates for LibreS3+dependencies but was waiting for the C backend to get packaged upstream first. My slides from last year list a few more problems that I encountered during development but they aren't an issue currently [4]. The main advantages of OCaml for me are: - the availability of high-level libraries that makes implementing HTTP APIs simpler (Ocsigen, Cryptokit, atdgen, etc.) - event-driven/non-blocking architecture to support large number of concurrent users (Lwt) - native binaries and static type system - not having to look for certain bugs in my code like uninitialized variables, NULL dereferences, memory leaks or memory corruption bugs; which (used to) take up a significant amount of time when developing applications in C (although tooling on C side have improved with valgrind, clang -fsanitize= and Coverity). That doesn't mean that code written in OCaml or the libraries that I use doesn't have bugs, I track them down and provide patches just as I would for a C library. Although perhaps writing code in OCaml has made me somewhat overconfident in my code, and I find bugs in other people's code more easier than in mine even if I'm not looking for them. [1] http://gitweb.skylable.com/gitweb/?p=libres3.git;a=summary http://gitweb.skylable.com/gitweb/?p=libres3.git;a=summary http://www.skylable.com/products/libres3 http://www.skylable.com/products/libres3 [2] http://gitweb.skylable.com/gitweb/?p=libres3.git;a=tree;f=libres3/testsuite/docker http://gitweb.skylable.com/gitweb/?p=libres3.git;a=tree;f=li... [3] http://www.skylable.com/products/sx http://www.skylable.com/products/sx [4] https://ocaml.org/meetings/ocaml/2014/ocaml2014_13_slides.pdf https://ocaml.org/meetings/ocaml/2014/ocaml2014_13_slides.pd...
- mackwic 11y agothanks for your detailed answer. It's an interesting stack ! Using docker for integration testing seems like a good idea. > Although perhaps writing code in OCaml has made me somewhat overconfident in my code Many Ocamlers could be caught of overconfidence. It's hard to understate how ML typing help seeing the data flow.
- hacker_9 11y agoI'm not a user of OCaml, but here is a counter-argument for C#: First-class functions C# has closures, and can pass function pointers with delegates. -- immutability is the default Mutability can be a useful tool in some situations, but it is often unnecessary and potentially harmful. I think this point has probably been argued to death by now, but I still can't see this as a good idea. 'Side effects' are really just a reality of software development. For example if I want to fade in a GUI element on a page, I don't want to create a new element for every transition change. Theres nothing wrong with mutable state, but it is nice to have immutability for some use cases. In this case c# has valuetypes, and the const/readonly modifiers. -- Strong static type checking Yep C# has had this since the beginning. And you can even use 'dynamic' if you really want which moves all type checking to runtime. -- Algebraic data types and pattern-matching I feel like these are more buzz words than actual substance. The Html example given also doesn't seem exactly clear to me how the operations are being performed. Here's a pseudo c# way of doing it: rootHtmlElement .SelfAndDescendants() .OfType<DivElement>() .Where(d => d.Attrs["class"] == "foo" || d.Attrs["class"] == "bar") .Select(d => d.ChildElements.OfType<TextElement>().FirstOfDefault()) the typical object-oriented implementation of this in Java would involve multiple subclasses of a common base class. I assume they mean that all element types would inherit from a base IHtmlElement? This seems like a good thing to me. -- Type inference Again C# has these abilities with 'var a = 0' for example. It won't infer method return types, not because it couldn't, but because it's just generally clearer to have the explicit return type written there in the code for the reader. -- a replay-capable debugger C# has intelliTrace for this. Though I expect both suffer from the same problems, slow execution while in use, and huge memory footprint.
- cwyers 11y agoC# has actually been trying to incorporate as much from ML languages and Haskell as it can (look at Linq, for instance). And of course, F# is an ML family language with a strong resemblance to OCaml that runs on the CLR. Trying to attack OCaml by noting that C# has a lot of the same features kinda misses the arrow of causation here.
- hacker_9 11y ago
- sytelus 11y agoAnother naive arguments for why language X is better. Native and 3rd party libraries+frameworks far outweigh usability and productivity gains than few cool language features. Most features mentioned in article are available in mainstream languages at certain extent that is acceptable for professional development at scale. This is not to make case against OCaml - it is nicely designed language indeed - but the case should be made from beauty and "as matter of taste" perspective rather than productivity and business justification perspective.
- rwmj 11y agoPattern matching, strong typing with type inference and mutability by default are certainly not available in "acceptable" mainstream languages. Also OCaml is highly productive, very fast to run, and you can just call down to C when you need to use a library.
- vog 11y ago> Also OCaml is highly productive More precisely, OCaml allows me to refactor my code very quickly, finding almost all mistakes even before any testsuite runs. This is possible due to a combination of language features which only few languages have (notably, Haskell, SML and F#). Not sure how this goes into total productivity, but this acceleration in development speed is something that no number of frameworks or libraries can match up.
- dfan 11y agoI didn't use OCaml for that long, but I still remember being astonished at how trivial it was to refactor in it.
- sytelus 11y agoProductivity gains by well tested vast number of libraries and frameworks far far outweigh gains due to language features such as pattern matching. Sure you can drop down to C from pretty much any language but most setups attempt to minimize that because maintaining hybrid language infrastructure (build/unit tests/upgrades/logging/auth etc) is typically expensive over long run. Also, may be calling libraries may be ok but using entire frameworks is much harder to use cross language.
- rtl49 11y agoIn other words, they like the fact that it has features typical among languages oriented toward functional programming. There's no cost-benefit analysis here discussing the obvious pitfalls from a business perspective, such as a much reduced talent pool and probably higher salaries for the few programmers who are comfortable working with such an uncommon language. There's also no discussion about why they believe a business offering a calendar application needs to use such a technically demanding language. This would be more understandable for, say, Jane Street (high-frequency trading), but for this particular business my naive belief is that this probably will not be the "competitive advantage" they claim it is.
- fulafel 11y agoWhat are your reasons to believe the job market for hippy functional languages is charcteristically highly paid and a "seller's market"? Judging from some anecdotes and the proportion of FP programmers working in academia I would have thought the opposite. Unless you're looking for the shallow end of the talent pool...
- rtl49 11y agoMy prejudice is that anyone competent in functional programming is also comfortable with other programing paradigms, in particular OOP. Not so much the reverse. Thus the limited talent pool and higher wages.
- LeonidasXIV 11y ago> My prejudice is that anyone competent in functional programming is also comfortable with other programing paradigms, in particular OOP. That might be true, but if they are competent in both, that's often because they have switched from OOP to FP and prefer the latter nowadays so if there is a selection between otherwise equivalent jobs, they would tend toward the FP job.
- rtl49 11y agoPerhaps, as you suggest, attracting more talent is one benefit of using an FP-oriented language for their codebase. It would have been nice to see this claim evaluated in the context of a cost-benefit analysis including the costs. This article, which claims that OCaml provides a "competitive advantage," doesn't provide that. Thus I don't believe it is a useful source of information for evaluating the merits of OCaml in particular, or FP in general, in a production environment.
- thalesmello 11y agoOCaml is a nice language and it surely has advantages. But don't treat that as a competitive advantage. All of the benefits mentioned can be easily found in other programming languages, except for maybe pattern matching, but that can be easily replaced with similar constructs. Using a not very popular programming language can actually make it harder for you to hire people.
- sklogic 11y ago> that can be easily replaced with similar constructs Mind giving an example? > Using a not very popular programming language can actually make it harder for you to hire people. Do you really want to work with people who can't learn a tiny little language?
- dozzie 11y ago>> that can be easily replaced with similar constructs > Mind giving an example? You can use, for example, elaborate if-else constructs that firstly try to determine type of the value, then check for values. I've never seen in imperative languages anything similar to conditional that checks both type and content of an expression, and allows to capture parts of that expression into variables. Well, except for precisely the pattern matching construct, where it was implemented deliberately after functional and declarative languages (Rust). >> Using a not very popular programming language can actually make it harder for you to hire people. > Do you really want to work with people who can't learn a tiny little language? I see things a little differently. It's extremely difficult to find an idiot who can write OCaml, while it's fairly easy for C++, Java, or C#. Also, allowing people to learn OCaml and use it every day on the job is a big plus for a company. It's way better than free sandwitches for breakfast in the long run.
- rlander 11y agoYou can use, for example, elaborate if-else constructs that firstly try to determine type of the value, then check for values. That's nowhere near pattern matching. Two concepts make pattern matching vastly superior to if-else constructs: - Non-exhaustive checks by the compiler. - Destructuring
- e_d_g_a_r 11y agoExtra note, now can install OCaml with npm, just $ npm install install_ocaml -g $ install_ocaml
- bsg75 11y agoGenuinely curious, why would someone want to use a Node package manager to install OCaml, instead of the more "traditional" approach - yum, apt, ... ? https://ocaml.org/docs/install.html https://ocaml.org/docs/install.html
- iamsohungry 11y agoI think you missed one of the most compelling things about OCaml: it's very arguably most performant system in existence which also provides the user with a strong type system. C/C++ provide performance but not a strong type system, which results in huge numbers of bugs. Other languages provide strong type systems, but in exchange give up a lot of performance. OCaml is somewhat unique in this combination of features. I say "somewhat unique" because there are other languages in this space: Rust in particular may be the language of choice for these feature needs in the future.
- andrioni 11y agoI thought F# and Haskell were at least on the same level of performance, if not faster. Is it not the case?
- ldrndll 11y agoAnecdotally, OCaml seems to often be faster than Haskell, though not necessarily materially so. More important though (in my opinion at least) is that it seems performance is more predictable in OCaml. High performance code in Haskell tends to rely on a combination of stream fusion, rewrite rules firing and judicious use of unboxing and bang patterns. I've heard it said that the OCaml compilers simplicity makes it far easier to know what code it's going to produce. Disclaimer: I'm a Haskell user, so it might just be that I'm more familiar with Haskell's warts.
- tel 11y agoIt's worth noting as well that the flambda branch of the OCaml compiler is starting to include lots of these advanced optimizations which will (a) probably improve performance, (b) make abstraction more "free" enabling more use of it, and (c) put a hit on performance predictability again.
- jlouis 11y agoThese questions often depend on how much time you are willing to spend making things fast. OCaml has an extremely predictable performance curve, which is nice when you are writing code that has to run fast. In turn, productivity is good because you don't get into situations where you have to rewrite code to make it faster in many cases. Even for brute-force algorithms, it tend to run fast enough that it would work well. Over F#, OCaml provides a module system. This helps programming in the very large. Over Haskell, OCaml provides a module system, and strict evaluation. The latter is a contended point, but proponents of OCaml claim it leads to memory/execution predictability. In Haskell (GHC) you often have to turn on optimizations in order to understand how your code will perform in reality, whereas byte-code interpreted OCaml acts just like natively compiled OCaml space wise, but is roughly 10 times faster in execution speed.
- lobster_johnson 11y agoI always thought OCaml looks like a language which should be fantastic for Erlang-style actor programming or Go-style network programming. Every few years I take another look. Last time I researched this, I came across a bunch of incipient attempts at distributed, concurrent programming frameworks, but they were all abandoned around 2009. I couldn't find any mature, maintained frameworks, any easy-to-use concurrency primitives (lwt has, to my untrained eyes, a terrible API and is no match for goroutines or Erlang processes), and apparently the global interpreter lock is still there.
- corysama 11y agoYou might be interested in http://www.ponylang.org/ http://www.ponylang.org/
- lobster_johnson 11y agoPony looks nice, but unless it's something revolutionary I just don't have the energy or patience to be part of the first wave of anything new. That's why I'm not, at this moment, using Rust or Nim in production. I want a mature toolset, a large, cohesive standard library, a large, active ecosystem, etc. Go only recently reached this stage. Node.js has been there for some time. Elixir is there thanks to leveraging Erlang.