3 ms·
I'll tell you my experience. I never liked the arguments about reduced bugs or concise code. As a programmer the reason I would use F# (or OCaml, or Haskell, or
by jasim 9y ago
I'll tell you my experience. I never liked the arguments about reduced bugs or concise code. As a programmer the reason I would use F# (or OCaml, or Haskell, or Elm, or PureScript) is because it increases by day-to-day well-being.
I'm happier writing Typed FP because the system is very concrete in my head as I work with it. In a dynamic language, there is always a nagging uncertainty about the system - if you're using dictionaries to pass data around, you don't have certainty in what keys it'll have, and what data will be available inside it, and what could possibly be null.
When you add a new kind of a domain object (a Guest user in a user management system for example), you have no idea where all you need to handle it. You fix the obvious places, and do a text search, and find a few more. And the rest you fix over time.
The runtime robustness of untyped systems in my experience generally is a function of time. The more it sits in production, the more bugs we discover in the most commonly trafficked codepaths. We fix them - duct tape works - and then it sits and chugs along. (Robustness to change is another matter altogether).
But if you use a Typed Functional language, when you introduce a new domain object the compiler will tell you exactly where they are being used and will refuse to compile till you've made sure you're handling it in all the right places.
Value-based programming (ala Immutability) lets you write code as if you were writing mathematical definitions (high-school mathematics; no category theory or monad). While we can be disciplined about not writing mutating code, there is a real difference between 99% confidence and the second-guessing it entails, and just not having to worry about it at all. Everything is a value. There are no objects/references.
All this adds up to a state of clarity when you program. You don't have to keep second guessing yourselves; you don't have to do defensive checks that makes you feel a little bit ugly inside; you don't have to deploy worrying about the unknown unknowns that can break your system.
- nurettin 9y agoIn Delphi, I hide this kind of complexity behind methods which check everything for nulls and types at runtime. I imagine I'd do the same thing in C#, too. So if I have json = TJSON.parse('{}'); json.Node['something'].Nodes[0].each(procedure(pNode: TJSONNode) begin; list.add(pNode.GetValue<int>()); end); { Nodes and Node properties actually create empty nodes and keep a debug string to show you where exactly your code failed so you can go back and take a look at which assumption was wrong. I then cleanup everything when the main node is freed. So my point is; it all depends on how you code something, the language may do it at compile time to prevent runtime assertions, but that also comes with extra baggage (I assume you need to write more code to define your types, function call conditions and mappings)
- zubspace 9y agoYour response raises some intersting points and sounds reasonable. But also kind of too dreamlike. Is it possible to seamlessly integrate a user managment system in f# into existing c# code? I guess, it's not that simple. It also reminds me of an experience I had in a former job with C++. There was a very, very experienced senior who wrote a very clever library which allowed us to add varous metadata to domain objects in a a compile-time checked, type-safe and very performant way. When the guy left, everything went downhill and the code from then on was regarded as mysterious black box noone dared to touch. Somehow I am reminded if this when I read about 'magic' solutions in FP. Is it possible to reach a state with FP where seeing through it all gets too troublesome?