4 ms·
OCaml is not my primary programming language, but I have been looking at it among many other options including all of the ones you mentioned. The module system
by jordwalke 12y ago
OCaml is not my primary programming language, but I have been looking at it among many other options including all of the ones you mentioned.
The module system of OCaml is very powerful, and a similar module system is not present in F#, or anything else besides some variants of StandardML as far as I know. I was able to accomplish many things using Functors that I have not been able to accomplish in any other languages.
Here's a link to one of my previous comments regarding some of OCaml's compelling or unique features:
https://news.ycombinator.com/item?id=7861033 https://news.ycombinator.com/item?id=7861033
At the time of writing that, there were a couple of reasons why you still might consider Haskell instead of OCaml (assuming you were willing to accept complete purity and were willing to adapt to lazy evaluation). Those two primary reasons were type classes and a multi-core runtime (where immutability would really shine). I don't know much about Haskell, but this is what I've heard from other well informed people. I'm sure there's many other great reasons to use Haskell over OCaml, but these were the main ones from what I could tell.
But since then, it looks like there's been great progress on an OCaml multi-core runtime, and also something very similar to type classes (module implicits). We'll have to see how those develop but it's definitely exciting.
Also since then, Jeffrey Scofield has accomplished a lot to get OCaml working on modern iOS systems so you can build native iOS apps with OCaml:
http://psellos.com/ocaml/compile-to-iphone.html http://psellos.com/ocaml/compile-to-iphone.html
I've been building a small project in OCaml for a while now, and my experience hasn't left me wanting any core language feature that some other language has, aside from possibly a multi-core runtime (I haven't actually needed it yet, but I will soon). Most of the things I wish were different are very superficial syntactic gripes - but OCaml supports arbitrary syntax via ppx extensions so I can just stop complaining and build the syntax I want to program in. (Haskell-inspired syntax? Swift-inspired syntax?).
The only other feature I'd like to see is a unification of the object system and record system: You could describe that as "row polymorphism" built into records (complete with pattern matching). No other major contenders support this, so it doesn't effect my language decision, yet it would be a welcomed feature.
- frowaway001 12y ago> The module system of OCaml is very powerful, and a similar module system is not present in F#, or anything else besides some variants of StandardML as far as I know. Scala's module system is very similar to ML's. Object ≅ Structure Class ≅ Functor Trait ≅ Signature Abstract Type ≅ Abstract Type Refinement ≅ Sharing Constraint
- kvb 12y agoThis is roughly correct, but see Andreas Rossberg's caveats here[1] for some considerations that may be important depending on what you're trying to do. [1] http://stackoverflow.com/a/23019436/82959 http://stackoverflow.com/a/23019436/82959
- jordwalke 12y agoGreat point. And many of these distinguishing features mentioned in that post are the ones that I used in order to accomplish some very powerful abstractions that I couldn't have done in any other language that I've tried. (Functors operating on types and values).
- a0 12y agoExcellent overview, OCaml is quickly becoming a powerful and flexible tool in almost all aspects comparable to other languages and has its own unique strength like module functors and polymorphic variants. > The only other feature I'd like to see is a unification of the object system and record system: (...) Could you elaborate a little bit on this or maybe point an article about it? Thanks.
- jordwalke 12y agoI'm not the best person to elaborate, but I'll explain from my limited knowledge. OCaml actually has a very complete object system (with ugly syntax, but don't judge). It's similar to OO you're used to in Java etc, but the types are often inferred instead of requiring that you state up front that classes/objects are subtypes of other classes. It allows you to use objects just as you would records, except: 1. You don't have to predefine the object types anywhere - with records you do. 2. With OCaml "objects", you get inferred "row polymorphism", which means that you can make a function (without any type annotations) that accepts a point, and accesses point.x, and point.y. This function will also, gladly accept a 3D point that has an extra field point.z, that the function never accesses. In OCaml, you never even needed to predefine a type for 2DPoint or 3DPoint. This is similar to, but different than the OO "subtyping" that you're used to in OO languages. 3. Records don't provide this "row polymorphism" that OCaml objects provide. 4. Records do allow pattern matching. 5. I would like to see the best of both. Pattern matching and row polymorphism into one new record abstraction. I'm sure there are tradeoffs (likely something to do with predictable memory layout accommodating efficient instructions). Row polymorphism may make type inference times longer, or error messages less readable. I'm definitely not the right person to give an overview of this - so please do your own investigation on the tradeoffs. I'd love to hear an expert chime in. But all in all, I'm happy with records and the performance I see. Named arguments (with optional defaults) (which OCaml has) can fulfill the role of a unified record/object system, in some cases.
- wtetzner 12y ago> But since then, it looks like there's been great progress on an OCaml multi-core runtime, and also something very similar to type classes (module implicits). We'll have to see how those develop but it's definitely exciting. Is there any information about these that I could read?
- logicchains 12y agoModular implicits: http://www.lpw25.net/ml2014.pdf http://www.lpw25.net/ml2014.pdf The multicore runtime: http://www.lpw25.net/ocaml2014.pdf http://www.lpw25.net/ocaml2014.pdf Recent presentation on the multicore runtime: https://www.youtube.com/watch?v=FzmQTC_X5R4 https://www.youtube.com/watch?v=FzmQTC_X5R4
- mercurial 12y agoSome things I'd like to see are a single unified stdlib, more use of sequence types and have the toolchain streamlined (death to Makefiles).
- tikhonj 12y agoHaskell is getting row polymorphism[1] for records (going under the name OverloadedRecordFields) in the next release. The new language extension will also play well with lenses, making records even more versatile. However, we're still not getting special syntax for field access, so it'll be function application (g f) instead of a dot (f.g). This isn't a major drawback, but it means that a field g has to be in scope for this to work at all. Fundamentally, it seems exactly the same approach could be used to give Haskell polymorphic variants. They're not part of this extension, but I wouldn't be surprised to see them in the near future. Haskell is also getting a much better (ie not crippled) module system soon, in the form of Backpack[2]. However, I'm not sure when this is actually going to be released—I don't think it's in the upcoming version. [1]: http://www.well-typed.com/blog/84/ http://www.well-typed.com/blog/84/ [2]: http://plv.mpi-sws.org/backpack/ http://plv.mpi-sws.org/backpack/
- freyrs3 12y agoFrom the talks I've seen Gundry usually tends to qualify comments about OverloadedRecordFields by saying it's not traditional row polymorphism ( i.e. Record { name :: String | r }) ). It doesn't allow row extension or row restriction as first-class constructs in the type system. Although we can build these things as secondary features on top of the language as many libraries currently do though.
- jordwalke 12y agoWhen you say it's not first class, you mean that it can only be inferred?
- freyrs3 12y agoInference is orthogonal, I mean that a records don't have a distinct type in the type system. So structurally the following types are the same in Haskell, except one elaborates out a selector function. data Foo = Foo { name :: String } data Foo = Foo String What row polymorphism does is give use first-class record types that give us a measure of structural typing so that records with the "same" fields can be used in the same type and "larger" records can inhabit "smaller" types if the fields subsume. So we can write down a function like: foo :: forall r. { a :: Int, b :: Int | r } -> Int foo x = x.a + x.b The current proposal doesn't give us this. But we can still simulate it even if it isn't in the language.