My main gripe with ML variants is the poor syntax around async (F#). For networked (web) applications, you begin to find that many or most of your functions are async, and wrapping them in computation blocks which come with their own internal syntax that eliminates a lot of the elegance of ML and makes your code look more imperative often feels like it defeats the purpose of the language.
In F#
let Foo =
async {
let! data = getData() |> Async.AwaitTask
return data.value
}
let foo = task {
let! data = getData()
return data.value
}
In F#, you interoperate with Task<T> transparently, and there is a number of community libraries to further enhance the experience. It also supports nice combinators like and! out of box.
Comments
My main gripe with ML variants is the poor syntax around async (F#). For networked (web) applications, you begin to find that many or most of your functions are async, and wrapping them in computation blocks which come with their own internal syntax that eliminates a lot of the elegance of ML and makes your code look more imperative often feels like it defeats the purpose of the language.
In F#
Is this the best they can do? C# just has Ive always wanted ML syntax like this: I just dont write a ton of pure functions which have no I/O dependenciesYou can write a helper method (or use FsToolkit.ErrorHandling[0]) to simplify the F# example to:
And it'll be easier to work with the .NET ecosystem if you use the task computation expression[1] over the async one.[0]: https://github.com/demystifyfp/FsToolkit.ErrorHandling
[1]: https://learn.microsoft.com/en-us/dotnet/fsharp/language-ref...
Isn't that a synchronous call?
We have exactly that in OCaml. Check out Eio.
This is outdated.
In F#, you interoperate with Task<T> transparently, and there is a number of community libraries to further enhance the experience. It also supports nice combinators like and! out of box.