3 ms·
But no. The point was to show how when you're thinking in a language that supports algebraic types and pattern-matching, you automatically exclude states that
by DanielBMarkham 11y ago
But no.
The point was to show how when you're thinking in a language that supports algebraic types and pattern-matching, you automatically exclude states that can't exist.
It's not that the underlying CLR or IL is any different given the same solution -- that's just measuring a language's verbosity. It's that some language constructs automatically lead you down the path to correct code without having to boil the ocean.
Sidebar: I would have tightened the F# code up a bit. No need to have the Name string repeated in both types.
- inglor 11y agoOr, you could use a class Hirarchy with a User abstract class and ActiveUser and DeletedUser subclasses and use the type system to enforce the constraints. Using a nullable field and an enum is hardly the standard way in C#.
- nbevans 11y agoBut unfortunately it is the one a lot of C#'ers reach for because it is the smallest amount of code in that language and often results in the least refactoring effort. A properly designed model in C# like suggested is a large number of lines of code. And then because there is no pattern matching, you have to hand-roll your type checks/casts and make sure have that method throw an unconditional exception at the end for literally impossible states. Then if you make a change to this model, i.e. you add a new "SuspendedUser" subclass, you have to make sure you go through the codebase to update all those places you wrote a hand-rolled "pattern match" against that type. Because the compiler won't warn you about an unrepresented state on your type checks. And so then you have to make sure the whole project team is aware and you have to make sure new hires are familiar with the patterns being used. So yeah, the problems just snowball and then you wonder why you didn't just use a more appropriate language in the first place that has already taken complete care of all these trivial programming issues.
- rottyguy 11y agoBut then the article should be titled "Functional vs Non Functional approach to solving xxx" as opposed to c# vs f#. I think the OP was saying you could do it functionally in c# albeit less elegantly.
- 15155 11y agoDiscriminated unions, pattern matching are common but not universal features of functional programming languages.
- alkonaut 11y ago> The point was to show how when you're thinking in a language that supports algebraic types and pattern-matching, you automatically exclude states that can't exist. That should be the default line of thought in OO too! I admit it's easier to do with discriminated unions, but that doesn't change the fact that the C# class is still a common but poorly designed type in C#. The job of any type system is to make invalid states unrepresentable. F# has powerful tools for that, and make it intuitive and succinct. C# has fewer and less powerful tools, but it's still possible (and usually necessary) to use those tools! The equivalence of F# DU's are C# class hierarchies, and the equivalent of pattern matching is virtual methods. Inheritance and virtual methods is a really verbose and horrible way of going about it, but it's the way of going about it in C#. You have to use classes for the state here Since there is a deleted time only useful for the "Deleted" state of the user the user state shouldn't be an enum. It's one of the pillars of decent OO design: a you don't have a field in a type that is only used for some state of the type: that state should then be a subtype. The possible state values for the user is ActiveState and DeletedState { DeletedTime }. If a person wrote the C# class in that way out of ignorance rather than laziness, I bet they would write the F# type as a normal record type too!