* Object programming with F# is based on .NET objects
* Generics in F# are based on .NET generics
* Reflection-based features are based on .NET reflection
* Structs in F# are based on .NET value types
* Newer features in F# 4.5 are based on newer .NET features
* Forthcoming nullability features will be based on nullability annotations in .NET metadata
It's impossible to divorce the two, even if the target runtime environment is not necessary a .NET runtime. Those other environments inherent language design decisions made with .NET as a target runtime. The .NET runtime with .NET Core is indeed minimal, is natively supported just about everywhere, and was built with cross-platform in mind. F# is a part of this, for better or worse.
[0]: http://fable.io/
It would surely be a lot of work, but “impossible?”
I think you’re missing a couple of major tricks by not doing a native code compiler for F#:
1. Now that Moore’s Law^H^H^HBusiness Rule has run dry, we can’t continue to just pile up the abstraction layers. Some sage once said that every problem in CS can be solved by adding another layer of abstraction, but there’s one that can’t: make it faster without buying more hardware. Given how popular FP is among the quants, a field often going after microsecond latencies, I’d think this would be a constant refrain from potential customers.
2. I don’t want to ship a dotnet runtime to my customers. Just this morning, I had to update a customer accessible only via a highly restrictive VPN, where they haven’t given my server DNS access, much less unfiiltered Internet access. Everything I ship to them has to be scp’d to the server over the VPN. I really really don’t want to send each such customer hundreds of megs of dotnet runtime stuff, then be forced to work around the failure of “dotnet restore”, so I’m going right back to C++ so I can get native binaries.
Hundreds of megs might be charitable. I just did a “du” of /usr/local/share/dotnet on a workstation here and got 1.4 GB. Presumably that compresses down to mere hundreds of megs. Contrast the size of a “Hello world” binary, which I’d expect to be under 10 kB.
I want to like F# on dotnet, but you’re making it hard for me to use it in practice.
A development environment includes the .NET SDK, shared framework, and NuGet packages. So that's going to be large in size. But you should never distribute the SDK with a published application. That's pushing a development environment onto a production machine.
If you then try to get that lower by using self-contained builds, you can only get "Hello, world!" down to about 20 MB:
$ dotnet new console --language f# -n hello
$ cd hello
...add <RuntimeIdentifier>osx.10.13-x64</RuntimeIdentifier> to fsproj
$ dotnet publish --self-contained -c release
$ cd bin/release/netcoreapp2.1/osx.10.13-x64/publish
$ rm -r ?? ??-?? zh-* # nuke i18n
$ tar -cvJf ~/Desktop/hello.tar.xz .
You'll notice that I'm giving you the benefit of high compression here. The unpacked tree is 70 MB!The equivalent in C++ is 3.3 kB.
I'm not expecting miracles. As I said, I'd be happy with "only" a 3x ballooning here, roughly commensurate with the coding efficiency benefit. That's fair.
1. Cleaner syntax. F# shows that we can do away with a lot of the visual noise in OCaml. I’m no particular fan of white space scoping, but I also don’t mind it.
2. Much better thought out standard library. The OCaml standard library was clearly accreted over long periods, with no strong designer making hard choices about naming and such. The example that keeps coming back to me is “big_int” vs all the other integer data types.
I believe #2 is what the OP meant by “minimal runtime.” A minimal F# will still need a good set of data types, a string library, etc.