Hacker News new | past | comments | ask | show | jobs | submit login
Functional Programming as a Competitive Advantage – A Real-World Use-Case (medium.com/datarisk-io)
13 points by b-man on Dec 15, 2021 | hide | past | favorite | 5 comments



Did anyone else find this article lacking? I was hoping to learn a bit more about real world examples of functional programming, but all this really did was state some high level ideas of what you could benefit by using a functional programming language like F#.

It is still not clear to me what the advantages of using a functional language like F# vs writing C# code that avoids side effects and mutating objects in functions. If anyone could share any articles or books on the subject, I would really appreciate it.


> It is still not clear to me what the advantages of using a functional language like F# vs writing C# code that avoids side effects and mutating objects in functions.

Personally, the thing I like about functional languages is that good practices are often the default way of doing things. For example, in OCaml, you can create mutable values with "ref", or a record with mutable fields with "mutable". You also have access to mutable arrays. But the default is immutable values, records and lists. Same thing with the compiler/type system: Hindley-Milner is a great default. OCaml also has a whole object-oriented system that works well, but the default is plain functions and data structures.

The difference between C# and F# or OCaml isn't as big as before these days. But having good defaults is, I think, very important.


> I was hoping to learn a bit more about real world examples of functional programming...

Watch any of Rich Hickey's talks on YouTube if you want to hear more about the advantages of functional programming.


> writing C# code that avoids side effects and mutating objects in functions

If you write C# like that, you'd have an ugly F#


F# person here. Unfortunately I agree with you - the article doesn't really live up to the title. I'm going to assume that you're coming from C#. F# is unquestionably a superior language if you're doing LOB work. (Part of being an F# fan is knowing what it's bad at, and it's bad at game programming & perf compared to C#. This isn't to say F# is slow - but it's slow-er than C#.)

"Domain Modeling Made Functional" by Scott Wlaschin is excellent. It's in F#. His "railroad oriented programming" talk drove home the benefit of discriminated unions, which C# is... someday going to get. (It's been a WIP for years.) https://vimeo.com/113707214

Avoiding side effects makes reasoning about code simpler. If you call a pure function, you know it doesn't effect anything else in the system. It doesn't mutate its arguments, it doesn't call a web service, etc. This means you can memoize it. What you see is exactly what you get. *In contrast, imagine writing code that must return `void`. The only way you can "return" a value is by mutating the arguments.* Now to be fair, eventually you must side effect in order to have any reasonable program (i.e. printing to the console is a side effect), but the goal of FP is to push side effects to the boundary of the system.

This also enhances testability. Your "core" is pure and easily testable, and your IO can have its own integration tests. My personal definition of "unit test" is a test of pure code. If it does IO, it's an integration test. F# is also wonderful in that it has FsCheck (and Hedgehog.Fsharp). Property based testing is a fantastic rabbithole to get into, and these days the majority of my unit tests are property based.

Where F# shines is when there's intrinsic, essential complexity in the domain. (Distinct from infrastructure complexity - F# doesn't have any real advantage if all your complexity is in IO). However, even something as simple as "user input validation" may count as domain complexity. For example in my domain, I have a discriminated union who's cases are `IdempotentError` and `UserInputError + string`. In the case of an IdempotentError, I just report things are groovy back to the user. For a `UserInputError`, I display the associated string. That string may/should be a type if you're starting to do internationalization. In C# you would need to do a ton of run-time if-checks or polymorphism to do the above. Yuck. In F#, these checks are enforced by the compiler. You literally can't forget to handle an error case.

Lastly, F# virtually eliminates all null errors. Its option type is wonderful, and C# only wishes its nullable reference was as simple.

I personally learned F# through Advent of Code. F# has a REPL which is ideal for these types of problems. Here's a blog and video about it: https://www.compositional-it.com/news-blog/a-brief-introduct... https://www.youtube.com/watch?v=_QnbV6CAWXc&t=1298s FYI F# notebooks is now out of preview, so you can use normal VS Code (and not the Insiders version).




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: