> it's a high-level language with static types, so easy to make large scale changes as we figure out what the language/product was
> you mostly model data with sum types, which in my mind are the best way to model data
>it's very similar to the language I wanted to build (in particular, we could reuse built-in immutable data structures for Dark's values)
> it had a reputation for being high-performance, which meant that we could write an interpreter for Dark and not have it be terribly slow (vs writing an interpreter in python, which might be too slow)
> We have struggled to make editor tooling work for us.
> Lack of libraries
> Multicore is coming Any Day Now™, and while this wasn't a huge deal for us, it was annoying.
> we also use ReasonML
> lazyness and pure functional-ness I felt were not great
> I plan to leave keep the frontend in ReasonML
You want a statically typed functional (but not pure) language with sum types, immutable data structures, good performance, editor/IDE support, a broad library ecosystem, multithreading, a C-like syntax (I assume, since you're using ReasonML), and a nice compile-to-Javascript experience to run in the browser.
I don't want to sound too much like a fanboy, but all this really sounds like Scala. You want Scala.
Scala.js generates significantly larger bundles than Rescript — because Ocaml's semantics map more closely to those of JS, the runtime dependencies are smaller and there's a lot of tricks to minimize indirection/overhead. Additionally, interop with npm modules is much less painful with Rescript and bindings for popular third party libraries are more mature. Ignoring the merits of Scala-the-language, there are very good reasons to pick Rescript over the Scala.js toolchain.
In the small, Rescript generates smaller code than Scala.js, that is true. It is mostly a question of the interdependencies in the standard Scala collection library, though, not so much the semantics of the language. And Scala.js also has its share of "tricks" (aka optimizations) to reduce indirections and overhead.
Yes, Rescript has more built-in types that map straightforwardly, but that is at the cost of some correctness. For example, using a JavaScript array means that JavaScript can resize it under your feet. Using `undefined` to represent `None` means that you cannot tell the difference between `None` and `Some(None)`. It's a fine trade-off to make. Scala.js happens to make the other trade-off, and offers separate types for JavaScript interop.
I like the concepts and design of Rescript, really. It's very interesting because they have all the essential requirements right (IMO) like comprehensive JavaScript interop, while making all the opposite design decisions on nonessential trade-offs compared to Scala.js.
Rust doesn't work well as a purely functional language. You'd be constantly fighting the type checker for memory issues. (Or otherwise, why doesn't Haskell take the same route as Rust and ditch its garbage collector?)
There is a library called py.ml [0] that lets you call Python code from OCaml. That should let you use Google Cloud's Python SDK from OCaml, although things could get unwieldy if you have to call back and forth constantly. I think it's at least worth a try, especially if the alternative is rewriting your whole codebase in Python.
> When you're searching for product-market fit, you do the simplest, easiest thing. If you lack a good SDK for your cloud provider, the simplest, easiest thing is often a terrible architectural choice.
I understand his point here. Spending week(s) writing a good SDK is hard to justify, but if you're building new infrastructure to support a project in a more obscure language, you kinda have to sacrifice time building said infrastructure well. When Naughty Dog programmed their games in GOOL/GOAL they built their own compilers, debuggers etc. - not a trivial task.
Content on HN about the holy trinity of programming languages, text editors, and operating systems generally favors less popular options with more mystique. Anything about Java is probably going to be largely neutral or negative, while a piece on Common Lisp might be much more positive, even though Java is a far more successful programming language in most ways.
I don't think that this bias is a bad thing. It's nice to read about cool technologies that you might not use in your day job. But anyone using HN to decide on the right tool for a project should carefully consider other sources of information as well.
Assume for the moment that all languages are equal. (They aren't, but ignore that for the moment.) If you say something good about Java, there are a lot of people here who have used Java, and some of them have bad impressions that they came to through some pain.
But if you say that Common Lisp is great, there are fewer people who have really used it, so fewer people who have used it and didn't like it. And since fewer people got into it unless they really wanted to, it's easier to say "You didn't really understand it, then, or you would have liked it." The number of people who can say "No, I really got it, and I still didn't like it" is relatively small.
So far, that's just demographics. But then you get into the language itself. Java isn't an exciting language. It's not fun. It's kind of corporate and bland. There aren't many people who are really enthusiastic about Java - nor does Java give them reason to be.
OP here. I don't mean this to be negative, this is just my ongoing developer blog to keep the Dark community appraised about what's going on.
There's some really great stuff about OCaml. I don't think we could have gotten through the first 2 years without OCaml, we repeatedly made very large scale changes to what our product was and how it worked, and that would have been 10x harder in something else.
Expecting open source developers to write a well-tested proprietary SDK for a vendor is going to be hard ask. If you need that and unwilling to do/fund the work yourself, just stick with vendor supported languages.
I would turn this around. As a guy who was doing OSS here and there (and still got burned out by doing only a little) I completely sympathize that nobody should ever expect people to do important work for free. Absolutely.
At the same time, it's a good response when somebody muses in a saddened manner "I wish my favourite language was more popular". Then I can spring out of the bush and tell them why it isn't. This doesn't mean I expect the OSS community around the language to serve me -- of course not! But it's a good explanation on why language X isn't more commercially popular.
I used OCaml for several years professionally. It's a phenomenal language in many ways, but there's no way I'd seriously consider using it for a new project at this point.
I don't really agree on the "Learnability" and "Minor annoyances" sections here. In terms of overly academic discourse, well, everyone's experiences differ but that's simply not a problem I've personally seen in the community (and I'd happily tell you other languages have that problem in spades). In terms of learnability: Ocaml, (the good parts) is an extremely straightforward language in most respects. The tutorials on the Ocaml website are enough to get you up and running, and Real World Ocaml is freely available and it's great. It'd be nice if v2 ever came out, but...well. Between those two, if you're still struggling, give me a call and I'd be happy to tutor you :)
The rest of this article hits most of the nails right on the head. The library support just isn't there, the community is too fragmented (why is stdlib vs. Core vs. Batteries and Async vs. Lwt still an issue?), the tooling is still too rough. OCaml's lack of multicore isn't actually a problem for most use-cases, but the fact that it's been in limbo for a decade despite the endless clamouring for it tells you something about what you're hitching your wagon to.
Twenty years ago OCaml would've been a no-brainer. At this point if I wanted a practical garbage-collected language I'd choose Scala and get a large and active community, as many Java libraries as there are stars in the sky, and the most sophisticated runtime environment mankind has ever dreamed of (for better or worse). If I truly need a compiled language, well...tragically, I've been bitten by the Rust bug (to the extent that I'm starting to believe its rigid approach to ownership helps engineer better code - that the ability to freely and thoughtlessly sharing references to objects the way garbage collection grants makes it a mistake, but that's a story for another post). And if I need 100% of the power and safety types can give me, Haskell is there waiting, with a better ecosystem to boot. Everything OCaml does well other languages do better, and then some. It's an also-ran now.
> I'd choose Scala and get a large and active community, as many Java libraries as there are stars in the sky, and the most sophisticated runtime environment mankind has ever dreamed of (for better or worse).
Hahahaha oh wow. You never ever used Scala, aren't you? I did, I moved from OCaml to Scala.
Oh, good luck joining Scala community then, we don't have aforementioned problems, don't we? Because Akka vs Zio vs Cats vs Scalaz is not a thing. Because ensime vs metals debacle never happened. Because we don't rewrite the complete ecosystem each couple of years.
> most sophisticated runtime environment mankind has ever dreamed of
Which you need to tune quite a lot to fit Scala into it (hopefully, it's very tuneable). Oh, and this "most sophisticated runtime" doesn't support TCO btw.
Oh, and any AnyRef value (so anything but basic types) can be null, thanks, runtime.
I love Scala, but all these "I wouldn't choose OCaml, I would choose F#/Clojure/Scala/other obscure language" usually mean "I've tried ocaml but didn't try other obscure language, so maybe it's better"
I love OCaml is well, and most of your points could be reduced to simply "it's lacking manpower" (Scala is lacking it too).
Because all of the "why is stdlib vs. Core vs. Batteries and Async vs. Lwt still an issue" we have in C, C++ and many other popular languages too, but it's not a big issue. People complain on meson/cmake/autotools/boost/glib/qt but not leave for some reason.
Maybe people don't use OCaml that much rather because there are simply too few jobs and too few programmers and it's a simple chicken and egg problem. And all these technical rationalization is not the reason because it's applicable to quite a lot of languages (safe for lack of libraries)
Yep, I completely get the "the grass is NOT greener on the other side" sentiment. I've been a victim of it many times and I am much more careful these days.
> I love OCaml is well, and most of your points could be reduced to simply "it's lacking manpower" (Scala is lacking it too).
For the better or the worse, this is literally the #1 priority one has to have before trying to technically evaluate a language / framework these days. Otherwise you get sucked on a joyful ride at the end of which you find lack of employability. :(
I personally much prefer OCaml's syntax but since Rust has much more mindshare and is mostly serving the same niche (with GC being the apples-to-oranges comparison here), I preferred to work with Rust. I still would like to work with OCaml but the odds are stacked against the financial incentives of doing so.
> Because all of the "why is stdlib vs. Core vs. Batteries and Async vs. Lwt still an issue" we have in C, C++ and many other popular languages too, but it's not a big issue. People complain on meson/cmake/autotools/boost/glib/qt but not leave for some reason.
Sure, many other languages suffer from that but it's still a very good ideal to strive for -- namely have very few (ideally one) ways of doing things. I personally look for such languages / frameworks and sadly they are very few and far between (Elixir and Clojure come to mind as refreshing exceptions and even they don't follow it everywhere).
---
In the end, we all do this for money. If I could work without charging for it then I'd likely know more languages and even work more overall, but it's not the reality we are living in currently.
So...I think a decent choice to make here is to switch from OCaml to F#. You'll get almost all of the benefits and most of the drawbacks go away. And for the most part, you can directly translate the code from OCaml to F#.
The big reason to not use F# vs OCaml tends to come down to the lack of functors... but it looks like your current codebase might not be using them much.
I enjoy f# a lot, but it doesn't necessarily help with all of their problems.
One of the biggest problems they mention is with postgres. F# has a postgres problem as well.
Your options in f# for postgres usage include the following high-level categories:
• Dapper/RepoDb/Other community libs
• Typeprovider based like Fsharp.Data.Npgsql
• EF core (where you build the fsharp design-time support yourself)
• Using C# in another project as a database interaction abstraction
I've had to mix and match for the projects I've worked on because I've had trouble finding a single library where:
1) Joins are supported in a sane way
2) Batch inserts work
3) Interacting with native features (views, functions, SET variables) works
4) It's still in fsharp
It's not bad, but when I work on $DAYJOB projects in Typescript/etc where database access is smooth, I wonder how long it might take to rewrite for the database heavy projects.
Also should mention that I'm very thankful for the libraries that _do_ exist, and the effort put into making them as feature as they are. It's just one of the areas that I don't think is a strength of F# right now.
I've done quite a bit of F# Postgres in a previous life and I didn't find it much different than other programming languages. However I tend to just use the Npgsql library directly with ADO.NET for performance which I often needed for my cases with Postgres. These days you can insert array objects, insert whole objects graphs, do batch inserts and create little helpers to read/write sets with Npgsql/PSQL directly; often much faster than using a higher level ORM. In my experience Postgres often would produce query plans that required a lot of SQL tuning/rewriting in a different way to get right (e.g. loose index scan SQL to get latest entry per group). I just wrap the solution/build with DB tests to make sure the SQL is covered well vs using the type provider. Tbh the amount of code (in lines) is mostly the same as well to do it vs a higher level framework - we did the comparison.
Have you looked into Linq2Db [0]? (I'm a contributor to the project) I know a few F# users have had success with a couple of minor caveats. I can say it handles most of the points you mentioned fairly well however (Great join syntax, lots of bulk insert options, easy wire-in for native features.)
But those are all database abstraction mechanisms or ORMs. Regular SQL access to postgres databases is pretty much a fully solved problem in F#, even if the ORMs are not.
If you're writing a while platform with a new ide concept, built in deployment and your own framework on top. (darklang) I think an ORM is the least of their problems.
They'll not going to pick F# because they're in competition with Azure.
They don't want ocaml because of marketability. It's technically the right choice and direction but the learning curve for developers is turning them off the platform as a whole.
I tried doing that for my program and failed miserably, mostly because CLR is not optimised the same way the OCaml runtime is optimised to minimise copying of memory. As a result the (direct translation of the) program became more than 5 times slower, which was a deal breaker for this use case.
Yes, there are ways to write it in a .NET-y way in F#, but then it requires a "complete" rewrite and F# gives no real benefits with "being similar".
Of course, this is also a full-rewrite without using the same idioms as in OCaml (mostly because I mutate objects directly when needed) but I still think it's much better than F# as the language (Rust) is miles ahead in the practicality domain. Indeed, it's much better than anything I've seen so far. And still so very much "functional" and "elegant". I just miss the transparent currying from OCaml.
> You'll get almost all of the benefits and most of the drawbacks go away.
That's a bit overstatement. You can call .Net code from F#, just like you can call Java from Clojure or Python/Rust/C from OCaml.
It just would be foreign and unidiomatic (hello, null pointers, methods, OOP).
And you can call C/Python/Rust from OCaml, we made quite a lot of wrappers for Gstreamer and some Rust libs in OCaml and it was quite painless.
So it's a bit of simplification, you can call foreign code in OCaml, it's not that much harder than F# considering there are higher level FFIs for C, Rust and Python available. Author could just use these as well.
Writing an F# wrapper for a C# API is considerably less involved than writing an OCaml wrapper for a C API.
This is because F# and C# share:
* build tools
* package management
* garbage collector
* base types (string, int, etc).
The F# type-checker understands C# types, so you know that you are consuming the C# API correctly (at least at the type-level). F# can be be used as a new syntax for C#, if you wanted to go that way.
I was thinking the same all throughout the reading. I've been using F# on GCP in production for 3 years now and it's fantastic and only getting better. You can leverage existing .NET libraries (for example, you get official GCP libraries from google) and if you use them enough it's easy enough to write a functional wrapper around them. I recently rewrote the frontend using Fable.React so that I can share code between backend and frontend.
Those are an implementation of functors as they exist in Haskell. The functors I'm talking about are actually a language level construct that is a primary abstraction mechanism in OCaml/SML. They are essentially higher-level modules: modules that are parameterized by other modules.
OCaml functors are not the same as Haskell/F# functors/applicatives (which are essentially one and the same in OCaml if you use named arguments).
Instead, they're roughly "functions from modules to modules": https://dev.realworldocaml.org/functors.html. Functors allow you to replicate much of what classes/objects in an OO language offer, but with static instead of dynamic dispatch.
In OCaml, "functors" are parametrized modules—mostly unrelated to functors and applicatives in the Haskell sense. Think about it as a module that can take another module as an input.
I was thinking the same thing. Using multicores and having a library ecosystem (through interop rather than conventional F#) should be a win. I don't have an idea what performance difference to expect but certainly closer to OCaml than Python even for single-core.
At least as of a couple years ago, OCaml wins on performance for anything single core, but not by much. F# is usually within a 5-10% performance gap. Absolutely better than Python.
I wonder if anyone has built a list of functions, libraries and toolings that are considered as essential among mature Programming Languages. Not the core features but ecosystem around it.
So that when people are evaluating a PL, they can known immediately what is missing. And people wanting to make a new PL knows what is missing in their ecosystem, the community can jump in to help.
Mostly due to interest in FP being driven by intrinsic desire to use it, since it's so rare in enterprise. Anyway, a lot of that discussion filters down into more popular languages, so it's pretty incorrect to think of it as all academic junk or something.
It is much less of a problem with OCaml than most non-OCaml users would expect. OCaml isn't Haskell; if you want for loops and similar generic imperative features you can have them!
The problem is there is no middle ground. FP people forget about the product because of FP. Alot of non-FP people forget also forget about their product because their are swamped with unecessary maintanence. There is a middle road in there somewhere where you use just enough FP to avoid the problems you would face without it, without getting totally sucked into making it perfectly consistent.
> you mostly model data with sum types, which in my mind are the best way to model data
>it's very similar to the language I wanted to build (in particular, we could reuse built-in immutable data structures for Dark's values)
> it had a reputation for being high-performance, which meant that we could write an interpreter for Dark and not have it be terribly slow (vs writing an interpreter in python, which might be too slow)
> We have struggled to make editor tooling work for us.
> Lack of libraries
> Multicore is coming Any Day Now™, and while this wasn't a huge deal for us, it was annoying.
> we also use ReasonML
> lazyness and pure functional-ness I felt were not great
> I plan to leave keep the frontend in ReasonML
You want a statically typed functional (but not pure) language with sum types, immutable data structures, good performance, editor/IDE support, a broad library ecosystem, multithreading, a C-like syntax (I assume, since you're using ReasonML), and a nice compile-to-Javascript experience to run in the browser.
I don't want to sound too much like a fanboy, but all this really sounds like Scala. You want Scala.
Compare https://rescript-lang.org/docs/manual/latest/shared-data-typ... with how Scala.js represents arrays and records.
Regarding interop and the link you posted, here is the equivalent documentation page in Scala.js: https://www.scala-js.org/doc/interoperability/types.html
Yes, Rescript has more built-in types that map straightforwardly, but that is at the cost of some correctness. For example, using a JavaScript array means that JavaScript can resize it under your feet. Using `undefined` to represent `None` means that you cannot tell the difference between `None` and `Some(None)`. It's a fine trade-off to make. Scala.js happens to make the other trade-off, and offers separate types for JavaScript interop.
I like the concepts and design of Rescript, really. It's very interesting because they have all the essential requirements right (IMO) like comprehensive JavaScript interop, while making all the opposite design decisions on nonessential trade-offs compared to Scala.js.
:)
You the author or something? I'm actually learning F# and OCaml and am interested in Scala as well.
[0] - https://opam.ocaml.org/packages/pyml/
I understand his point here. Spending week(s) writing a good SDK is hard to justify, but if you're building new infrastructure to support a project in a more obscure language, you kinda have to sacrifice time building said infrastructure well. When Naughty Dog programmed their games in GOOL/GOAL they built their own compilers, debuggers etc. - not a trivial task.
I don't think that this bias is a bad thing. It's nice to read about cool technologies that you might not use in your day job. But anyone using HN to decide on the right tool for a project should carefully consider other sources of information as well.
But if you say that Common Lisp is great, there are fewer people who have really used it, so fewer people who have used it and didn't like it. And since fewer people got into it unless they really wanted to, it's easier to say "You didn't really understand it, then, or you would have liked it." The number of people who can say "No, I really got it, and I still didn't like it" is relatively small.
So far, that's just demographics. But then you get into the language itself. Java isn't an exciting language. It's not fun. It's kind of corporate and bland. There aren't many people who are really enthusiastic about Java - nor does Java give them reason to be.
Moving from OCaml to C++ or Go would be a drastic and surprising change, but it's not nearly like that.
There's some really great stuff about OCaml. I don't think we could have gotten through the first 2 years without OCaml, we repeatedly made very large scale changes to what our product was and how it worked, and that would have been 10x harder in something else.
I actually think OCaml stands to be in a great place in the next few years with the work being done by core community members. See https://twitter.com/patricoferris/status/1323330884515356672.
Also why not to choose F#/Mono (and now .NET core) for example?
At the same time, it's a good response when somebody muses in a saddened manner "I wish my favourite language was more popular". Then I can spring out of the bush and tell them why it isn't. This doesn't mean I expect the OSS community around the language to serve me -- of course not! But it's a good explanation on why language X isn't more commercially popular.
I don't really agree on the "Learnability" and "Minor annoyances" sections here. In terms of overly academic discourse, well, everyone's experiences differ but that's simply not a problem I've personally seen in the community (and I'd happily tell you other languages have that problem in spades). In terms of learnability: Ocaml, (the good parts) is an extremely straightforward language in most respects. The tutorials on the Ocaml website are enough to get you up and running, and Real World Ocaml is freely available and it's great. It'd be nice if v2 ever came out, but...well. Between those two, if you're still struggling, give me a call and I'd be happy to tutor you :)
The rest of this article hits most of the nails right on the head. The library support just isn't there, the community is too fragmented (why is stdlib vs. Core vs. Batteries and Async vs. Lwt still an issue?), the tooling is still too rough. OCaml's lack of multicore isn't actually a problem for most use-cases, but the fact that it's been in limbo for a decade despite the endless clamouring for it tells you something about what you're hitching your wagon to.
Twenty years ago OCaml would've been a no-brainer. At this point if I wanted a practical garbage-collected language I'd choose Scala and get a large and active community, as many Java libraries as there are stars in the sky, and the most sophisticated runtime environment mankind has ever dreamed of (for better or worse). If I truly need a compiled language, well...tragically, I've been bitten by the Rust bug (to the extent that I'm starting to believe its rigid approach to ownership helps engineer better code - that the ability to freely and thoughtlessly sharing references to objects the way garbage collection grants makes it a mistake, but that's a story for another post). And if I need 100% of the power and safety types can give me, Haskell is there waiting, with a better ecosystem to boot. Everything OCaml does well other languages do better, and then some. It's an also-ran now.
Hahahaha oh wow. You never ever used Scala, aren't you? I did, I moved from OCaml to Scala.
Oh, good luck joining Scala community then, we don't have aforementioned problems, don't we? Because Akka vs Zio vs Cats vs Scalaz is not a thing. Because ensime vs metals debacle never happened. Because we don't rewrite the complete ecosystem each couple of years.
> most sophisticated runtime environment mankind has ever dreamed of
Which you need to tune quite a lot to fit Scala into it (hopefully, it's very tuneable). Oh, and this "most sophisticated runtime" doesn't support TCO btw.
Oh, and any AnyRef value (so anything but basic types) can be null, thanks, runtime.
I love Scala, but all these "I wouldn't choose OCaml, I would choose F#/Clojure/Scala/other obscure language" usually mean "I've tried ocaml but didn't try other obscure language, so maybe it's better"
I love OCaml is well, and most of your points could be reduced to simply "it's lacking manpower" (Scala is lacking it too).
Because all of the "why is stdlib vs. Core vs. Batteries and Async vs. Lwt still an issue" we have in C, C++ and many other popular languages too, but it's not a big issue. People complain on meson/cmake/autotools/boost/glib/qt but not leave for some reason.
Maybe people don't use OCaml that much rather because there are simply too few jobs and too few programmers and it's a simple chicken and egg problem. And all these technical rationalization is not the reason because it's applicable to quite a lot of languages (safe for lack of libraries)
> I love OCaml is well, and most of your points could be reduced to simply "it's lacking manpower" (Scala is lacking it too).
For the better or the worse, this is literally the #1 priority one has to have before trying to technically evaluate a language / framework these days. Otherwise you get sucked on a joyful ride at the end of which you find lack of employability. :(
I personally much prefer OCaml's syntax but since Rust has much more mindshare and is mostly serving the same niche (with GC being the apples-to-oranges comparison here), I preferred to work with Rust. I still would like to work with OCaml but the odds are stacked against the financial incentives of doing so.
> Because all of the "why is stdlib vs. Core vs. Batteries and Async vs. Lwt still an issue" we have in C, C++ and many other popular languages too, but it's not a big issue. People complain on meson/cmake/autotools/boost/glib/qt but not leave for some reason.
Sure, many other languages suffer from that but it's still a very good ideal to strive for -- namely have very few (ideally one) ways of doing things. I personally look for such languages / frameworks and sadly they are very few and far between (Elixir and Clojure come to mind as refreshing exceptions and even they don't follow it everywhere).
---
In the end, we all do this for money. If I could work without charging for it then I'd likely know more languages and even work more overall, but it's not the reality we are living in currently.
The big reason to not use F# vs OCaml tends to come down to the lack of functors... but it looks like your current codebase might not be using them much.
One of the biggest problems they mention is with postgres. F# has a postgres problem as well.
Your options in f# for postgres usage include the following high-level categories:
• Dapper/RepoDb/Other community libs
• Typeprovider based like Fsharp.Data.Npgsql
• EF core (where you build the fsharp design-time support yourself)
• Using C# in another project as a database interaction abstraction
I've had to mix and match for the projects I've worked on because I've had trouble finding a single library where:
1) Joins are supported in a sane way
2) Batch inserts work
3) Interacting with native features (views, functions, SET variables) works
4) It's still in fsharp
It's not bad, but when I work on $DAYJOB projects in Typescript/etc where database access is smooth, I wonder how long it might take to rewrite for the database heavy projects.
Also should mention that I'm very thankful for the libraries that _do_ exist, and the effort put into making them as feature as they are. It's just one of the areas that I don't think is a strength of F# right now.
[0] - https://github.com/linq2db/linq2db/
Same thing exists from MS SQL https://github.com/Zaid-Ajaj/DustyTables , also great.
Used both in prod. No regrets and wouldn't wan't something else. Also involves zero magic - just raw SQL and a nice functional API.
They'll not going to pick F# because they're in competition with Azure.
They don't want ocaml because of marketability. It's technically the right choice and direction but the learning curve for developers is turning them off the platform as a whole.
Yes, there are ways to write it in a .NET-y way in F#, but then it requires a "complete" rewrite and F# gives no real benefits with "being similar".
In contrast, after that I migrated to Rust and I am delighted. I wrote about it here: https://news.ycombinator.com/item?id=24893285
Of course, this is also a full-rewrite without using the same idioms as in OCaml (mostly because I mutate objects directly when needed) but I still think it's much better than F# as the language (Rust) is miles ahead in the practicality domain. Indeed, it's much better than anything I've seen so far. And still so very much "functional" and "elegant". I just miss the transparent currying from OCaml.
That's a bit overstatement. You can call .Net code from F#, just like you can call Java from Clojure or Python/Rust/C from OCaml.
It just would be foreign and unidiomatic (hello, null pointers, methods, OOP).
And you can call C/Python/Rust from OCaml, we made quite a lot of wrappers for Gstreamer and some Rust libs in OCaml and it was quite painless.
So it's a bit of simplification, you can call foreign code in OCaml, it's not that much harder than F# considering there are higher level FFIs for C, Rust and Python available. Author could just use these as well.
This is because F# and C# share:
* build tools
* package management
* garbage collector
* base types (string, int, etc).
The F# type-checker understands C# types, so you know that you are consuming the C# API correctly (at least at the type-level). F# can be be used as a new syntax for C#, if you wanted to go that way.
What do you mean by that? F# has support for functors, or are you referring to something else? https://fsprojects.github.io/FSharpPlus/applicative-functors...
https://stackoverflow.com/a/16353711
Instead, they're roughly "functions from modules to modules": https://dev.realworldocaml.org/functors.html. Functors allow you to replicate much of what classes/objects in an OO language offer, but with static instead of dynamic dispatch.
So that when people are evaluating a PL, they can known immediately what is missing. And people wanting to make a new PL knows what is missing in their ecosystem, the community can jump in to help.
I had the impression that's a general problem with FP.
Deleted Comment
OCaml/ReScript/Clojure people seem to be a bit more chill.