What should F# as a language contain?
- A default test framework like Expecto
- A default HTTP client like HTTP.fs
- A default web framework like Suave
- A default JS framework like Fable
- A default logging framework like Logary
- A default character parser combinator library like FParsec
- A default binary parser combinator library like FsAttoparsec
- A default concurrent programming framework like Hopac
- A default "RoP"/monadic naming standard (Monad.result | Monad.return | Monad.pure | Monad.create | ...) as a document – exemplified in YoLo.fs
Now that those exist; that they are split up and in part absorbed in what can be thought of a F# Core library; but what really is a collection of abstract libraries.
So from the above "getting started pack", we abstract for Web:
- Binary HTTP parser combinators from Suave, to use with the default binary parser combinator library
- Stateless HTTP parsers from Suave, but even better from Freya's HTTP-header model into an object model we can share
- Stateless HTTP generators from HTTP.fs (as the generative side of the above model)
- Stateless HTML view generators from Suave.Experimental https://github.com/SuaveIO/suave/blob/master/src/Experimental/ViewEngine.fs and Giraffe and Fable's view generators
- Stateful engine for TCP from Suave, Kafunk
- Stateless engine for HTTP / like Freya's graphs
-- Ensuring these can be compiled and run in the browser, React Native and server, to get "isomorphic/universal F#" apps
Hopefully, by splitting these things up, we can avoid constraining these libraries and types within monads (avoiding Freya's freya-monad, Suave's SocketOp/async monads). And we can start to make F# a first-class compile-to-JS language.
To avoid getting eaten to Task, we can make it easier to work with Hopac; we need people to learn and start enjoying it. The compiler authors in Fable/F#/F#-compiler-services can work together to find a subset that F# promises runs in the browser; thereby improving safety and avoiding runtime bugs. This would allow us to take up the fight with Elm, ClojureScript and similar compile-to-JS eco-systems.
From the above, we abstract for Test:
- An asseration library from Expect.fs (can live as Expecto.Assertions, to start with)
- A runner library from Expecto.fs (similarly as Expecto, to start with)
- From Logary Facade.fs, and Expecto and in the long haul, with the enrich-with-information-at-call site functionality (file name, file line, type names, etc) of the compiler, we can make logging and testing in F# apps much easier
- A HTTP testing framework from Suave.Testing -- Because we ensured the Web things above can also run in the browser, we can now easily compile domain models and server-side code to the browser/React Native and use the mocha runner to run the unit tests (without the user necessarily knowing they are using mocha)
If we can do the above, we have really good primitives that can be extended by libraries – these would cut both Freya and Suave and Expecto in half. We've also brought the testing story on par with go test
/rspec spec
. The binary parsers that we switch the web story to, removes the frequent complaint that F# is a slow language for system programming and we can start showing how the language competes with Rust.
The stateful engine for TCP extracted from CLR's Socket/Everest/F* lets us further the language support for model-driven testing, which leads us to more powerful primitives by default. We can compose models of TCP with the model we created for HTTP with the app model that is WebMachine aka Freya, to explore almost all state-space.
The binary parser combinators/generators lets us move forward with writing system-software with F#, and that in turn lets us port things like the americal fuzzy lop fuzzer to F#, like Go has done, but vastly more efficient since it can be informed to explore the program state space structurally with the above created object models.
Because we start to create core abstractions like the binary parser (FsAttoparsec), we can also cooperate on making those zero-copy; perhaps taking a leaf from the Nom parser combinators (https://github.com/Geal/nom) – in terms of work for FsAttoparsec, there's a need to prove safety and termination, increase performance and work on the buffer management (contrast to FParsec that has a highly optimised buffer management).
If we can write the above in a safe subset (without reflection as much as possible) of F#, we can in five years time look forward to turning the output of the F# compiler towards webassembly and thus to compile-to-binary-OS, like apps written for MirageOS.
F# as a language should not contain any of these. What it should have is a viable advancement model, a fast compiler, full .NET Core support, and a working integration into various IDEs.
If you mean "what should F#'s standard libraries contain", no, they should not contain any of these either. If they did, there wouldn't be any of the diversity, innovation or competition we all love about F#, nor any of the community/people politics some hate. The former keeps the language and the community around it growing (a healthy part of which you and I belong to: people with commercial interests and viable offerings), while the latter feeds people who prefer to mud the waters for a temporary advantage and/or community fame.
You are right about WebAssembly, but it should come from Microsoft and it should come right now, and despite what some think, it won't replace JavaScript nor the language-to-JS ecosystem around it for a long while.