10 ms·
A new F# compiler feature: graph-based type-checking
- peheje 3y agoF# is sooo great
- owlstuffing 3y agoType providers are boss. Why doesn’t every language type system have this feature by now?!
- Akronymus 3y agoBecause they are pretty annoying to implement and most are quite fragile
- eddythompson80 3y agoThey are only as fragile as your type source.
- FrustratedMonky 3y agoMaybe not 'fragile' as in buggy, not buggy, but I found them to be 'quirky'. Sometimes stop working unless I close /re-open VScode. Stuff like that. And other downfall. Do they still not work with DOTNET Core??
- chusk3 3y agoThey've worked for several years now on dotnet, but the type provider author has to do some work to allow their type provider to compile and target that runtime.
- owlstuffing 3y agoYep, implementing one (a solid one) is hardcore. But think about it. Building, say, an XML or SQL type provider is a big deal. Doing it right requires special talent, because you are essentially building a transpiler to seamlessly interface with F#. But this is also it’s greatest strength. Having direct, type-safe access to structured data is truly awesome. What else compares? Certainly not conventional code gen.
- Akronymus 3y agoOh, don't get me wrong: Type providers are absolutely fantastic. Just, they are such a complex beast, most implementations I used so far are pretty fragile, at best. But tbh, even a fragile one is surprisingly useful
- eddythompson80 3y agoI got downvoted on the typescript subreddit when I mentioned how Type providers work in F# because "nah, it can't be working that way. The compiler can't be making http requests to make up types for an API" smh.
- Smaug123 3y agoIn fairness it is rather terrifying :P personally I pull all necessary information into some form of version-controlled storage, and then have a test to assert that the remote information is consistent with the stored version. Life's too short to have nondeterministic builds.
- eddythompson80 3y agoyeah that's fair. That's what I landed on too, and would think anyone using it seriously would be doing the same. But the fact that you could extend the compiler to program your own code generation in F# itself is amazing. Comptime in Zig reminds me of this too. I'd have to think OCaml has something similar, but I'm not too familiar with it.
- owlstuffing 3y agoJava has this too with the Manifold[1] project. It’s mind blowing. 1. https://github.com/manifold-systems/manifold https://github.com/manifold-systems/manifold
- eddythompson80 3y agowoah, I had no idea. That seems pretty cool
- PartiallyTyped 3y agoSQLX has entered the chat [1]. [1] https://github.com/launchbadge/sqlx https://github.com/launchbadge/sqlx
- CharlieDigital 3y agoCouldn't these also be done in C# via source generators?
- AlexErrant 3y agoNo. > How do Source Generators compare with Type Providers in F#? > If you’re an F# programmer (or familiar with the language), then you might have heard of Type Providers. Source Generators were inspired in part by Type Providers, but there are several differences that make them distinct. The main difference is that Type Providers are a part of the F# language proper and emit types, properties, and methods in-memory based on an external source. Source Generators are a compiler feature that analyzes C# source code, optionally with other files, emits C# source code to include back into a compilation. https://devblogs.microsoft.com/dotnet/introducing-c-source-generators/ https://devblogs.microsoft.com/dotnet/introducing-c-source-g...
- CharlieDigital 3y agoI get that the mechanisms are different, but the end result is the same. Edit: sample here with a JSON template: https://github.com/CharlieDigital/dn7-source-generators https://github.com/CharlieDigital/dn7-source-generators
- AlexErrant 3y agoAh, okay I thought that source generators had more limitations compared to F#. Turns out they can make arbitrary calls, including across a network, which previously I thought was only in the domain of type providers: > For Schema.NET, we do a HTTP request to get the JSON we need to build https://turnerj.com/blog/the-pain-points-of-csharp-source-generators https://turnerj.com/blog/the-pain-points-of-csharp-source-ge... Also phillipcarter says yes so I'll happily take his view over mine.
- phillipcarter 3y agoYes. The mechanisms are very different of course, but both the F# and C# components involved generate types with properties, methods, etc. that can populate IntelliSense.
- PartiallyTyped 3y agoIt's available to some in extend in rust, e.g. SQLX [1] allows you to typecheck queries. [1] https://github.com/launchbadge/sqlx https://github.com/launchbadge/sqlx
- xvilka 3y agoIf you think F# is great, check out the OCaml. F# is just a shadow of its glory with a couple notable exceptions.
- peheje 3y agoCan you elaborate? From what I have seen the performance of OCaml isn't up to par with F#. The std. library is small compared to all of dotnet, not to say the surrounding ecosystem and third party packages and tools. Syntax is of course subjective but to my eyes it's cleaner in F#. Idk. Don't want to start a war but rather hear specific arguments for why you like OCaml more.
- xvilka 3y agoMostly modules and corresponding type system features, AST transformation via PPX, better portability to non-x86 platforms.
- GiorgioG 3y agoGreat, now how about Microsoft stop treating F# like a redheaded stepchild? 99.999% of .NET shops will not touch it.
- owlstuffing 3y agoStatistically, functional languages _are_ redheaded stepchildren.
- peheje 3y agoWhile f# is definitely founded in functional paradigm. I feel like it's more a universal language. Like Kathleen says in her intro to f#6 https://youtu.be/jOrgDoMuFog?si=Dnu8kPPi5QS5rNOR https://youtu.be/jOrgDoMuFog?si=Dnu8kPPi5QS5rNOR "Im gonna do cool stuff like fold this unfold that. Dom said. Why don't you just write code?" (Paraphrasing it's first of the video)
- deleted 3y ago[deleted]
- moogly 3y agoI'm not sure the F# community would like it if MS took more control of it though.
- williamcotton 3y agoCan anyone recommend a good hard copy book for F#? One that covers the syntax, language features, and covers functional programming fundamentals along the way? Like, the F# book that Brian Kernighan would write?
- mdm12 3y agoI would recommend two. F# in Action [1] by Isaac Abraham is a great (and recent) introduction to the F# language. For a more philosophical, domain-oriented book, you can't go wrong with Scott Wlaschin's Domain Modeling Made Functional book[2]. Scott's blog[3] is also must-read material. [1] https://www.manning.com/books/f-sharp-in-action https://www.manning.com/books/f-sharp-in-action [2] https://pragprog.com/titles/swdddf/domain-modeling-made-functional/ https://pragprog.com/titles/swdddf/domain-modeling-made-func... [3] https://fsharpforfunandprofit.com/ https://fsharpforfunandprofit.com/
- williamcotton 3y agoI had discovered Scott’s blog in the last couple of days while searching for resources related to writing lexers and parsers in F#. It is indeed a great resource! Thank you for your other recommendations, I’ve just ordered both books!
- mdm12 3y agoEnjoy your F# journey! I have yet to find a more ergonomic, practical language for daily use :)
- akkad33 3y agoI don't know Brian is, but I would recommend Expert F#, a book cowritten by F# creator and BDFL Don Syme
- williamcotton 3y agoHe named UNIX, he invented the "Hello, world!" program, he's the K in K&R (The C Programming Language), he's the K in AWK, and he's the co-author of other classic works like The UNIX Programming Environment and more recently The Go Programming Language. He's currently a CS professor at Princeton. EDIT: Why the downvotes? It's just terse, it's not at all rude.
- bcherny 3y agoI was looking forward to the benchmarks. Did I miss them?
- anonzzzies 3y agoF# is so good, such a shame so few companies use it. I have to touch C# and it's always a little bit painful after a few weeks of F# work.
- arrow7000 3y agoF# is my go-to language for new backend projects and console apps. You can be as functional as you like, with imperative/mutable/OOP escape hatches available for those rare but unavoidable times you need them
- FrustratedMonky 3y agoHave to agree. Recently decided to try out Python instead. Everyone at work wanted Python, it's popular, so why not give it a shot. In constant regret, missing the type checking in F#.
- hmdw45 3y agoI haven't done so yet but I keep meaning to check out Fable's support for F#-to-Python: https://fable.io/docs/getting-started/python.html https://fable.io/docs/getting-started/python.html
- deleted 3y ago[deleted]
- eddythompson80 3y agofor console apps, F# sadly suffers from general .NET issues for console apps. Very large size (>150MB for a simple app) and at least 400-700msec startup time
- Smaug123 3y agoAOT compilation is actually usable in net7, and I'm told it's got much better in net8 - massively reduces startup time (and in net8 apparently binary size too)!
- JaggerJo 3y agoBtw. building GUI apps is super simple in F#. (mac, linux, windows, ios, android, web) https://github.com/fsprojects/Avalonia.FuncUI https://github.com/fsprojects/Avalonia.FuncUI
- peheje 3y agoAlso Fable is pretty cool https://fable.io/ https://fable.io/ Here build times are not really an issue as it seems to be hot-transpiling to js, so save and site is reloaded almost instant (at least small sites): My small tools site built with Fable: https://peheje.github.io/compare.html https://peheje.github.io/compare.html If you look at the JS - that's of-course the production minimized build, the transpiled JS is pretty nice and readable. Super simple site - vanilla JS seems wonderfully easy with F#, easy to hide its warts and build easy re-usable items. But there's of course also smarter stuff with two-way bindings via html annotation and builders etc. I am actually using Feliz.ViewEngine, which is building the HTML using F#, but only for the navigation bar. Might try converting a page to it.
- mumblemumble 3y agoI did a project using Avalonia.FuncUI a few years ago, and would highly recommend it. It made GUI development fun again.
- deleted 3y ago[deleted]
- twunde 3y agoThis is the type of feature that makes me want to use F#. Really great work, I would love to see similar work replicated in other languages (python's type checking libs especially). As an outsider it feels like the Bazel/Buck/Pants approach applied to type checking
- phillipcarter 3y agoThis is very neat, I love the idea of using the syntax tree to guide what can be parallelized vs. not. As some additional background, there's a very good reason why the F# language typechecks files sequentially. Because F# supports type inference at every scope, a single change in the body of a function can result in cascading type changes across an entire project. This kind of change can not only affect other files, but other files inside of other projects in the same solution. A way to curb these kinds of cascading changes is explicit type annotations and/or signature files, which "lock" the type signature for a given construct/file. And the F# compiler has had optimizations in place when signature files are used to know when to re-check stuff based on this. However, these didn't extend to the sequential typechecking of files, and for the large majority of codebases that don't use signature files, these optimizations didn't really kick in anyways.
- jeremyjh 3y agoThat's interesting. In Haskell top-level annotations are not required but I don't think I've ever seen a real project without them - its basically a community standard that's universally adopted, in a community that doesn't adopt many standards.
- daxfohl 3y agoIt's useful to keep these anyway, as if you make a change that accidentally changes the type of some function, the error message makes it immediately obvious what you did. Otherwise it's hard to tell whether you messed up the function or the caller. Also having type annotations makes code reviews easier. Basically people's brains can use the same optimization that compilers do.
- obeavs 3y agoGreat addition to a great language. We've been building a very technical product in F# + Rust for the last three years or so (think R lang + R Studio or Replit but for DSLs we built for finance and contracts). While most folks tend to see F# as a .NET-oriented/back-end kind of language, they'd be missing some incredibly unique web technologies such as the Fable compiler (F# -> JS, Python, Dart, etc) and Elmish (Elm, but for F# with a JS target via Fable). It boggles my mind that more of the web dev community haven't discovered these tools. These "communities" fall completely outside of MSFT's umbrella, but are transformative for how you think about architecting applications: Elm as an architecture (rather than as a language) enables a large amount of optionality in terms of what technologies one might use as a "reactivity layer" (e.g. can swap out React for SolidJS or even non-JS targets like Avalonia quite easily if it made sense to). Our bet is that it enables us to future proof things in a number of unique ways as better WASM-based solutions come online as well that hopefully won't require shipping the whole .NET runtime (e.g. Bolero). The approach is also v helpful in managing state across an otherwise very complex application.
- DarkNova6 3y agothis sounds exciting, but I wonder. How closely linked is Elmish to Elm? In theory Elm is just such a fascinating project... if it was not held back by the people developing it.
- arrow7000 3y agoIt's not linked at all, it just uses "The Elm Architecture" as inspiration to recreate the same architecture in F#
- carapace 3y agoPlease PLEASE enough with the character assassination of the Elm guy. He wants to run his own project his own way. There's a small but dedicated residue of people who just can't stand being told "no" and go around crapping on the kid whenever they get a chance. I get it. You don't like Evan's project management style. Move on already. - - - - The fact of the matter is that he's a person who took his thesis, made it into a product, and got traction in the real world. People have used Elm to make things. Things that go. How many of us can say the same? And that's before you get to all the fascinating and as yet still-too-obscure things that the OP talks about. Things that are in part a little more widely known and understood thanks to Elm project.
- aeonik 3y agoI have a tangential question that is related to this cool new feature. Warning: the question I ask comes from a part of my brain that is currently melted due to heavy thinking. Context: I write a fair amount of Clojure, and in Lisps the code itself is a tree. Just like this F# parallel graph type-checker. In Lisps, one would use Macros to perform compile-time computation to accomplish something like this, I think. More context: Idris2 allows for first class type-driven development, where the types are passed around and used to formally specify program behavior, even down to the value of a particular definition. Given that this F# feature enables parallel analysis, wouldn't it make sense to do all of our development in a Lisp-like Trie structure where the types are simply part of the program itself, like in Idris2? Also related, is this similar to how HVM works with their "Interaction nets"? https://github.com/HigherOrderCO/HVM https://github.com/HigherOrderCO/HVM https://www.idris-lang.org/ https://www.idris-lang.org/ https://clojure.org/ https://clojure.org/ I'm afraid I don't even understand what the difference between code, data, and types are anymore... it used to make sense, but these new languages have dissolved those boundaries in my mind, and I am not sure how to build it back up again.
- Arelius 3y ago> Given that this F# feature enables parallel analysis, wouldn't it make sense to do all of our development in a Lisp-like Trie structure where the types are simply part of the program itself, like in Idris2? Yeah, maybe, you for sure could, but in the context of F# as it exists, it may be hard to get from here to there. > 'm afraid I don't even understand what the difference between code, data, and types are anymore... it used to make sense, but these new languages have dissolved those boundaries in my mind, and I am not sure how to build it back up again. Yeah, good luck with that. I think maybe taking a mental step away from programing might help. It's true that human interpretation of the world often has these properties. And he generalization of the systems in no way invalidate the usefulness of the categorization system. Maybe it's helpfulnto consider the properties of your classes. To risk your further descent into madness. I recommend the Lambda days talk on the Verse programming language [1]. Which has further contemplation on the topics you are thinking about. With an eye towards practicality. [1]: https://youtu.be/OJv8rFap0Nw?si=XvUoBqO7IeCLIbrn https://youtu.be/OJv8rFap0Nw?si=XvUoBqO7IeCLIbrn
- yodsanklai 3y agoNoob question. I developed projects in OCaml (ocaml + opam + merlin + core/async) on linux/macos. I'm clueless about F#, I've always thought of that as some sort of JVM for Windows, not great for Linux. How would my experience compare if I was to use F#? not so much in term of language, but developer experience: IDE integration, richness of stdlib and third-party libs, build system, package management, tools stability.
- pzmarzly 3y agoI only tried F# for few days, but it was a pleasant experience on both macos and linux. dotnet CLI should take care of build process, it can even generate self-sufficient executable (that bundle parts of .NET in them). The infamous required XML boilerplate has also been cut down to near-zero. My biggest gripe is that Microsoft's debugger is closed-source and proprietary (though free for users of official VSCode builds). There is open-source netcoredbg by Samsung, so you can use VSCod[e,ium] with https://open-vsx.org/extension/muhammad-sammy/csharp https://open-vsx.org/extension/muhammad-sammy/csharp , but YMMV.
- Smaug123 3y agoJetBrains Rider is really excellent until you start getting up to like the 30-project mark. Stdlib is very extensive although has a bunch of annoying quirks due to being like twenty years old and due to having Linux retrofitted onto it; I have personally had to reimplement parts of its API from syscalls, but if performance isn't super-important for you then it's OK. MsBuild (the build system) and NuGet (the package manager) are both absolutely cursed, but if you are doing totally vanilla things then they're usable out of the box. The `dotnet` command line tools are weirdly inconsistent, sometimes buggy, and full of edge cases even in the places where they are self-consistent, but again if you're doing something super-vanilla then they should be fine.
- rpeden 3y agoYMMV with the build and package system depending on your experience. Sheet staying my career writing with JVM languages and then moving to C#, I far prefer MSBuild + NuGet over Maven or Gradle. But I know lots of folks who feel the opposite, so maybe it's just a matter of preference.
- devmunchies 3y agoIt would be nice if I stopped needing to update the fsproj file for imports and hierarchy. If this could be dynamically built using a topological graph approach that would be a huge improvement. I don't use a heavy IDE so it's kinda tedious to need to update the fsproj file when i want to add a new file.
- Smaug123 3y agoPersonally I strongly prefer F#'s way, and I always enable it manually in C# by setting `<EnableDefaultCompileItems>` to `false`. It's so much easier to debug e.g. compiler deficiencies/bugs when you can just binary chop to find the file that's causing a problem, and the reason you can do this is the linear ordering of explicitly listed files. (In C# I generally just give up and hope that someone else will do it, because it takes so much longer; in F# it's trivial.) What are you using as your development environment? Personally I don't find the overhead in Vim to be too onerous (`yypf"ci"NewFile.fs`), and even in Rider I routinely edit fsproj files manually. (I even create new projects mostly by hand.)