11 ms·
What I wish I knew when learning OCaml (2018)
- pharmakom 4y agoA good list. ML languages push you (kicking and screaming) into the pit of success.
- nnoitra 4y agoThey're barely used in industry.
- gpderetta 4y agoI wonder why this is the case. Ocaml syntax doesn't seem very arcane, it is not hell-bent on functional purism and pragmatically allows for imperative code. Performance seems quite reasonable. What does it lack that prevented it from gaining wider acceptance? Surely buy-in from a large company was an issue, but even F# hasn't seen any significant uptake. Is it really the lack of curly brackets? That didn't stop Python... Is it just that being labelled 'functional' was a huge stigma for a very long time?
- dgan 4y agoLibraries!!! Python is "batteries included" while OCaml barely has insulation around electrical wires. EDIT: okey that actually maight be a chicken-egg reasonning
- WastingMyTime89 4y agoIf Ocaml had been designed in the USA it would have been widely successful. It’s main drawback was being mostly a French project.
- usrnm 4y ago> If Ocaml had been designed in the USA it would have been widely successful I doubt that. There are plenty of American SML dialects and F# is about as American as it gets, but neither of these languages saw any commercial success.
- kragen 4y agoThe syntax is not great, the standard library is very sparse, and the error messages from the compiler and interpreter are terrible (and used to be worse). The OCaml team used to treat the native code compiler (ocamlopt) as a second-class citizen, but it's the implementation that matters for performance. Since the end of Dennard scaling about 15 years ago, OCaml's lack of multithreading has also been a pain point, one which is finally starting to improve in the last year or two. I don't think being labeled "functional" was ever a huge stigma. Being labeled "Haskell" is a huge stigma in some circles, but OCaml's never been labeled "Haskell". Until about 10 years ago functional programming didn't become popular enough to have any kind of popular opinion, positive or negative, and the people who knew about it generally thought it would be nice to do more of it. Mostly I think people use a programming language either because they already know it or it's the scripting language for an environment they have to use. Assembly was the scripting language for your CPU, especially in mainframe days. BASIC was the scripting language for personal computers. Visual Basic was the scripting language for WIMPs. VBA was the scripting language for Excel and Word (previously Excel had a table-based macro thing). sh was the scripting language for the Unix filesystem; C was the scripting language for the Unix system call interface, and a nice upgrade from assembly. JS was and is the scripting language for the browser. Lua is the scripting language for WoW, Roblox, and Minetest. Perl was the scripting language of the WWW, then PHP was, or Ruby if what you really want to script is Rails. SQL is the scripting language for your database. Objective-C was the scripting language for NeXTStep; now Swift is. MATLAB was the scripting language for EISPACK and later *PACK and BLAS, though it had some competition from IDL for a while. Now Python is the scripting language for Numpy (and thus BLAS), Matplotlib, and TensorFlow. Only a few popular languages are exceptions to this rule: Fortran, COBOL, C++, Java, R, Pascal, Golang, and C#. OCaml? OCaml is the scripting language of ocamlyacc and Coq. If you write OCaml then it's probably because you like Coq. This may have been a public relations problem in the Anglosphere, especially before same-sex marriage.
- wawjgreen 4y ago
- octachron 4y agoWhy do you think that the native compiler was treated as a second class citizen? This is quite strange take from my point of view. For instance OCaml native compiler was available on the M1 Macs two months after the M1 release. Similarly, all major CPU architectures (x86, ARM, PowerPC, RISC-V, s390x) have been supported for years.
- chii 4y agoIt's not that there's stigma, but that it is probably more difficult to think functionally when most programming education teaches imperative methods.
- asplake 4y agoBut look at their influence: TypeScript and Rust, not to mention Elm, PureScript and other less mainstream languages
- tgv 4y agoTypeScript is very much a C++ descedant, IMO.
- darksaints 4y ago+ Scala
- marginalia_nu 4y agoEven if functional programming itself isn't used, a lot of its patterns are extremely useful even outside of functional programming. Code returning side effects rather than having side effects, for example, is great, and I find myself returning to the principle in a lot of the stuff I design as an architectural principle.
- bmitc 4y agoKicking and screaming? ML dialects, or at least F#, are usually a pleasure.
- pmoriarty 4y agoI tried OCaml a long time ago, and one of the things that really turned me off of it was all the inscrutable error messages. I went to #ocaml on Freenode for help, and when I had the error messages explained to me I asked how the person who explained them knew what they meant. He told me that the reason he knew was because he took a couple of semesters of type theory courses at his university. I didn't want to have to take a couple of semesters of type theory courses in order to be able to program effectively in this language. I hope the situation has improved since then. The other thing I didn't like (which was something shared with other statically-typed languages) was feeling like I had to wrestle forever with the compiler to get my program to run. It just always felt so much easier to write programs in dynamically typed languages. Sure, my programs might have bugs in them, but I could iron them out over time, and my programs change so much anyway that pieces of buggy-but-working code in those dynamically typed languages might be replaced wholesale anyway before I even ran in to the bugs.. so the pace of prototyping in dynamically typed languages is much faster, in my experience.
- yodsanklai 4y agoI think both of these points can be alleviated with certain coding habits that come with practice. For instance, adding type annotations in some places will help with error messages. And using "assert false" (which has type 'a) will let you run an incomplete/broken program. As for the error messages requiring expertise in type theory, it sounds as an exaggeration, esp. when not using advanced features.
- pmoriarty 4y ago"adding type annotations in some places will help with error messages." I annotated the hell out of my programs, and completely avoided OCaml's type inference as much as I could because I saw that it could not guess what I meant. I still had tons of problems understanding the error messages. Error messages like "This expression is of type X but an expression was expected of type X" were not uncommon, and super frustrating.
- WastingMyTime89 4y ago
- dgan 4y agoTIL that Ocaml/SML are compiled into lambda expressions... I literally thought lambda calculus is only used in CS classes. OCaml's syntax is pretty annoying but type inference is actually amazing.. I changed my mind over it, as previously I thought explicit type annotations are simpler. Turns out, it would be humanly impossible to explicitly annotate every piece of OCaml, just let the compiler do it for you
- kryptiskt 4y agoGHC's Core language is amazingly small https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compiler/core-syn-type https://gitlab.haskell.org/ghc/ghc/-/wikis/commentary/compil..., and it's just polymorphic lambda calculus (with coercions added a while ago).
- eatonphil 4y agoDid you learn that from some other article? I couldn't find "lambda" in this page. I think it's too much to say that all Standard ML compilers work or one way or another. There are 6 major compilers and a number of minor ones. They don't really follow the same approaches in general.
- frou_dh 4y agoAt a higher level that that, it's cool that even in SML's already sparse surface-level syntax, quite of a bit of it is just sugar for each other: https://i.imgur.com/pkSg4xm.png https://i.imgur.com/pkSg4xm.png
- eatonphil 4y agoThat may be the semantics of it and for simple compilers that may be a true transform. But as compilers get more mature they tend to specialize everywhere they can so the actual compiler doing this under the hood may or may not happen.
- octachron 4y agoOne of the intermediary representation used by the OCaml compiler is a lambda calculus (https://github.com/ocaml/ocaml/blob/trunk/lambda/lambda.mli#L279 https://github.com/ocaml/ocaml/blob/trunk/lambda/lambda.mli#...). But yes, this is only the OCaml compiler.
- baby 4y agoshameless plug: learn with ocaml by example[1]. It is still heavily work in progress though, please feel free to create a PR :) [1]: https://o1-labs.github.io/ocamlbyexample/ https://o1-labs.github.io/ocamlbyexample/
- cassepipe 4y agoCould someone please explain ? : type 'a list = 'a :: 'a list | [] The article says "::" is a Data Constructor. I can make sense of type 'a = Left of 'a | Right of 'a where Right and Left are the Data constructors but I don't see the link with the part I don't understand.
- lifthrasiir 4y agoIt is equivalent to the following: type 'a list = Cons of 'a * 'a list | Tail ...but with a fancy syntax for Cons and Tail.
- cassepipe 4y agoOk. So in your example the construction action (placing two things next to each other IIUC) is done by the * product type Operator and Cons has no special meaning whereas if I had used ::, I actually get an the (::) name to refer to the left hand of the union and the construction action. Did I get that right ?
- kripke 4y agoSort of, I think? `type 'a t = Cons of 'a * 'a t | Tail` is defining a type with a constructor `Cons` with two arguments and a constructor `Tail` with zero argument. You write values of type `'a t` as `Cons (a, b)` and `Tail`. `type 'a u = (::) of 'a * 'a u | []` is defining a type with a constructor `(::)` with two arguments and a constructor `[]` with zero argument. You build values of type `'a u` as `(::) (a, b)` and `[]`. The rest comes from the special syntax support in OCaml for the `(::)` and `[]` names. Namely, `a :: b` is parsed as `(::) (a, b)`, and `[a; b; ...; z]` is parsed as `a :: b :: ... :: z :: []`, and hence as `(::) (a, (::) (b, (::) (..., (::) (z, []))))`.
- maweki 4y agoA list is either the empty list [] or Two pieces of data (with the constructor ::) with 1 being the head of the list (type 'a) and one being the tail of the list (type 'a list, a recursive definition). :: is an allowed identifier in oCaml. If that is not allowed, the typical names are Cons for :: and Nil for []
- bmc7505 4y agoML really is a beautiful and under-appreciated family of languages. Haskell is a bit too supernatural for my taste, but ML and its derivatives hit the sweet spot between powerful type systems and natural syntax. As a Kotlin developer, I find reading OCaml code a breeze and the compiler is refreshingly snappy (much faster than Gradle). I just wish it had better developer tools.
- throwaway894345 4y agoI like Rust for syntax, tooling, and ML ideas but I wish there was a "Rust-lite" that was garbage collected.
- ChadNauseam 4y agoIt's got its warts, but Ocaml (and ReasonML if you want a more familiar syntax) are right in that sweet spot for me.
- throwaway894345 4y agoI need to give ReasonML another shot. It's been a few years, but at the time it really only seemed to work if you were targeting BuckleScript and even then you had to write a bunch of Makefiles and jump through other weird hoops. Beyond that, it suffered from some other OCaml issues--multiple "standard" libraries, different packages using different async libraries, some gratuitously abstract libraries, etc. I'm really hoping it breaks into the mainstream such that it gets the investment that other mainstream languages get (hopefully said investment will smooth out these rough edges).
- Serow225 4y agothat’s pretty much F# :)
- mumblemumble 4y agoAs a long-time F# user and current Rust learner, I would say the similarities are mostly cosmetic. First and foremost, F# is functional-first, while Rust isn't really functional. Rust takes some useful features from functional languages, to be sure, but the overall paradigm is more procedural. A lot of key functional idioms and design patterns don't really fly in Rust because it's difficult-to-impossible to make them play nice with its memory management model. Rust has traits, but not OOP. F# has OOP but not traits or typeclasses. F# is immutable by default, and discourages mutability. Rust is immutable by default, but embraces (and tames) mutability.
- shikoba 4y agoThe golden rule is missing: > Don't try to understand the error message except if you have no other choice.