7 ms·
We're an F#-first company and I'd like to share our experience here. All our new code is in F#, we started off from a C# codebase, so that made the transition
by tejasv 6y ago
We're an F#-first company and I'd like to share our experience here.
All our new code is in F#, we started off from a C# codebase, so that made the transition somewhat manageable, as new F# code can be directly called from C#, and vice versa (still took over 2 years). All new frontend apps are also being written in F# (using Fable), as of 6 months back, migrating away from TypeScript, this forces everyone into a "design your model first, and well" paradigm. We've written quite a bit of code to blur the lines between traditional backend and frontend development roles, so what we have now are:
- product engineers (who write application logic on both frontend and backend to serve business needs)
- platform & framework engineers (who write the underlying persistence/serialization/versioning/frontend-backend-sync websocket/load balancing/IDE extensions/deployment etc)
- component designers who focus on visuals
Platform/framework engineers try to encapsulate as much magic as possible into computation expressions (F#'s monads), so product engineers can focus simply on writing out business intent, with readability given very high priority. We also make ample use of quotations to do some cool tricks (like predict the future states some type can take, based on current state + available transitions).
Our code written in F# has an order of magnitude fewer bugs when it makes it to production, given the amount of thought we pour in modelling the problem domain accurately, and thanks to functional programming itself. They're also more amenable to business requirements changing, simply because they've been modelled well to start with. Nothing that can't be achieved in other languages, but with F#, this happens more naturally.
Almost everyone in our team has learnt F# on the job, and overall, everyone's experience has been extremely positive. There's a bit of difficulty in the first 2-3 months, as junior devs get introduced to functional thinking, but if you've generally being doing functional programming, this is just about learning new syntax, tooling and F#'s choice of operator naming (map/bind/pick/collect/choose/..). Typically, based on prior experience, we ask newcomers to spend two weeks to a month, solving the first 100 problems on Project Euler in F#, without using the mutable keyword, and we assign a mentor to point out best practices and review their code.
The hiring pool for F# devs is much smaller than the regular applicant pool, but if a candidate shows genuine interest in F#, they are usually 10x more likely get through our interview process. If they've discovered F#, it means they find something lacking with mainstream languages, so they're likely to have many years of experience under their belt, and they've found a way to grow. That said, we don't restrict our hiring to simply F# devs.
For more info about us, see chaldal.tech (YC/S15).
- dfgdghdf 6y agoPlease can you sure more about this? > We also make ample use of quotations to do some cool tricks (like predict the future states some type can take, based on current state + available transitions).
- smt1 6y agoTake a look at F#'s type solver code especially wrt to Extension Typing: https://github.com/dotnet/fsharp/blob/main/src/fsharp/ExtensionTyping.fs https://github.com/dotnet/fsharp/blob/main/src/fsharp/Extens... You can do similar things with other Ocaml or Lispy Langs, depending on how you want to do it. All you need is a function that returns possibleTypeTransitions for givenType(type, enclosedLexeme, type.validTransitions). A gradually typed lang sitting in top of a prototype-based blob also makes this easy to do (see typescript) in-codo. See also MacKay (RIP)'s classic book: http://www.inference.org.uk/itprnn/book.pdf http://www.inference.org.uk/itprnn/book.pdf
- tejasv 6y agoHere's is a simplistic example of a state machine: let transition (state: State) (action: Action) : State option = match (state, action) with | (StateA, ActionA) -> Some StateB | (StateA, ActionB) -> Some StateC | (StateB, ActionA) -> Some StateB | _ -> None If you get the quoted representation of the transition function, it can be visualized as a tree data structure (like code-as-data in LISP). You can analyze that tree to understand that if current state is StateB, only ActionA can be applied on it. Couple this with another realization: "Any sufficiently complicated model class contains an ad hoc, informally specified, bug-ridden, slow implementation of half of a state machine." (not sure where I read this quote). This means all the entity framework/ORM crap work that we do can actually be neatly represented as transforms on a F# state machine, which suddenly makes the application more powerful if you give it this structure. We use this technique to auto-generate admin panels.
- xupybd 6y agoDo you blog any of this or do any sort of writing on the topic. I think I could learn a lot from the way you are doing things.