Hacker News new | past | comments | ask | show | jobs | submit login

This I don't understand: Seems like whenever functional paradigms are discussed, the whole same stuff is always repeated without failure: on one hand fuzzy generalizations like "pure functions", "no side effects", "no state"... on the other, all examples always talking about using map, filter, fold, flat, zip. One would think that "functional programming" _is_ using those functions. That FP is all about Iterators and what things you can do with them.

But I never see contrived real-world examples, those that really show how things are different from imperative or procedural programming. I want to see how you use stateless functional programming to control a garage door actuator. Or how you model a Car which can have their doors open or closed either by the class itself or external actors. How do you receive UDP packets, including a buffer implementation that is able to sort out-of-order packets and send retransmission requests for missing ones? That kind of stuff.

Are there any resources that show these kind of "here is a list of problems, how they are typically solved, and how you could solve with FP" style examples?

EDIT: This message was actually to say thank you and that TFA is an awesome resource to help understand how the Iterator methods work! And then I got lost in my semi-rant and forgot to actually say thanks :)

I'm currently reading Domain Driven Design Made Functional. https://pragprog.com/titles/swdddf/domain-modeling-made-func...

It shows how a functional approach can embed much of the domain logic into the types used. They are so simply expressed in F# that non programmers can understand what they say about the problem domain.

The book is selling me on the idea that Functional programming could do a better job in CRUD style business apps.

For anyone looking for a smaller introduction to this book, the author Scott Wlaschin has a talk with the same name: https://youtu.be/2JB1_e5wZmU

It doesn't cover a lot of good topics in the book, but it might whet your appetite.

I’ve found Grokking Simplicity [0] to be a great, pragmatic introduction to solving real-world problems with “functional thinking”.

All the code is JavaScript and it tries to walk you through how you might solve common, everyday business problems with a more functional approach. All without getting bogged down with terms like “monad” or “functor”.

This book (along with Domain Driven Design made Functional, mentioned elsewhere) are both great resources for getting introduced to “useful” functional programming.

[0] https://www.manning.com/books/grokking-simplicity

Thanks a lot for the suggestions and comments in this and other sibling comments, I now have for sure a bit of reading and learning to do!

> But I never see contrived real-world examples, those that really show how things are different from imperative or procedural programming. I want to see how you use stateless functional programming to control a garage door actuator.

I'm not sure why you'd want to see contrived examples, but the reason to focus on map, filter etc is that this is where it starts, and this is what functional programming _is_, transforming sequences of values with pure functions, rather than keeping a lot of state and change it imperatively.

How to write a real world program with functional programming is a later question, and pointless until you understood the basics. All your examples also include a bunch of concepts and data that A. can't be purely functional and B. will vary widely between programming languages, so they are very poorly suited for an introduction.

I agree. So, I guess what I mean then is that once you're past the usual introductions, there aren't many "next steps" kind of guides to start doing actual work with the functional mindset.

Although I must say, my examples are actual instances where I tried to put the shallow learning I had done about FP and failed spectacularly at doing so. It was no doubt due to my ignorance and lack of experience with FP, but maybe also there is a part of me not working with problems that lend themselves easily to a FP approach...

You are completely right that FP is lacking in guides that go beyond the basics. There's a great abundance of introductory material, but very little about how functional programmers structure large programs or deal with complex I/O.

That is way too much for me to put into a single comment, but the most common approach is to split your program into "pure" and "impure" parts and then model all of your interactions with the real world in a way where the "pure" part of your program becomes an "interpreter" that deals with the pure representations of real-world events.

A common pattern for doing this (but by no means the only one) is using Free Monads.

I'd argue this is true for most programming paradigms, and even some design processes. There's a lot of "draw the rest of the fucking owl" mindset when it comes to structuring and organizing code.

I guess it's a little easier with OOP, but it isn't very clear to me how "polymorphism" helps me open a garage door, or even achieves it's stated goals. I guess I can at least understand that now I can open any door by calling door.open() or something. Of course it gets much worse when you graduate and people tell you OPP is overhyped, there's too much abstraction here. Then you think "I thought the abstraction was good". Don't just create a garage door, create a door factory! Then you realize you don't have a good defense, and that you don't understand as much as you thought. You were never taught to design programs pragmatically. You just have to figure that part out on your own.

I can understand how mutable state causes problems and would be a good thing to avoid where possible. There's really not much needed to convince even a moderately experienced programmer, of the power of pure functions. It doesn't feel that far off from the OOP example.

The next step here may be recognising that just as you'd map a list, you can also map lots of other data structures, namely anything that's a functor (see: `fmap`).

Have something nullable? Stick it inside `Maybe` and map it.

Have a side effect in `IO` and want to manipulate the result? Map it.

Following that, look at monadic binding. It's basically flat mapping.

From here you can start to see how programs can be composed in languages like Haskell. You have these foundational typeclasses and you sort of just connect all your functions together with them until you're left with one big expression in `main` which is your application entrypoint.

I suppose it’s tricky to apply an FP approach when you get closer to the external interface, it’s moe suitable for the more internal stuff. But when you combine it with reactive approaches into FRP you can do more, and there are more complex examples to be found.

But I’d say in general that FP is mostly just an alternative to OOP, maybe even leas than that, not a complete paradigm for writing complex programs. At least if you use a mainstream language, then FP is probably something you do pretty locally.

FP can be used for the same solution, for which OOP would be used. In many (if not all) cases, the FP solution would be less complex.

The only caveat is in I/O mechanisms. An IO monad is one way to safely manage IO, but it is not the only way.

I’ve long struggled to “get” functional programming - both its syntax, and it’s real world uses. Everything is so terse and abstract and I find the lack of clear expressiveness to be daunting. It all often feels too “magic” to me which makes me suspicious. Then I wonder “what’s in it for me?” - how does it make my job or life easier? (I find myself much less motivated to learn something new without a clear answer to these things.)

One things I’ve found enlightening is when participating in Advent of Code exercises, watching how people are able to solve problems using functional languages. While I may not always grok the solutions in their entirety I’m often impressed by the compactness and elegance.

I share your experience. What worked for me and enabled me to grok FP was using Linq in C# (using the extension-method syntax, not the keyword-based syntax). It started-off with me wanting to avoid typing “foreach” everywhere when processing lists/collections/etc and then it all followed from there.

My only complaint about FP, and Linq in particular, is that it can often result in suboptimal execution when you have preconditions that Linq isn’t aware-of, such as a known input size, or known uniqueness of some key-property - and there isn’t a way to supply hints. And C#’s weak support for contravariance, aieee. Still lightyears ahead of Java though :)

All of the real world examples you described above involve I/O. There are various approaches for this, the most popular being the IO monad.

A function using the IO Monad looks like regular imperative code except for the type signature of the function which indicates that the function side effects and thus can only be called by other functions that side effect. Pure functions cannot call a side effecting function. This helps in isolating side effects and capturing it in the type signature of functions.

Plenty of examples here


Functional programming is not stateless programming. Rather it captures any state changes in the type signature. An explicit example of it would be the state monad.

Many functional languages do not model effects in the type system, like the ML family. Many do not have static types at all, like Clojure/LISP.

Those languages wouldn't be considered pure/stateless as intended by the OP.

Haskell would not be considered pure or stateless as well. What the OP is saying there are several qualities which indicate you are dealing with functional language and they are not super rigid. Typically first-class functions indicate that its possible to do things functionally. Immutable defaults takes it further. Higher kinded types usually indicate you can easily separate pure from effectful. Dependant types hint that you can have value level expectations etc.

At which point you are happy with "functional" is up to you. Its not all or none.

I share your opinion. I found the book Real World Haskell very useful http://book.realworldhaskell.org/ It has a few nice chapters about system programming, database interactions and a few other use cases.

Here is an educational bulletin board website built with Haskell: https://gitlab.com/gilmi/bulletin-app

Redux in the react world is a good example of real-world application using pure functions and functional programming concepts.

Likewise most of the hooks (useReducer being the obvious primary example), and functional components in general. That's how 99% of functional programming is done - state and function are separate, first class, concepts. The line is very distinct.

I don’t thinks hooks are a great example. Hooks are by definition effectful. Best compared to ‘Applicative’s in Haskell. (Not monadic unfortunately)

So a functional component in react using hooks is not pure. You can translate it into FP with a bit of magic, but requires a context. The line is not that distinct at all.

Hooks themselves may not be good FP examples, however I meant the resultant functional components that you develop yourself usually are.

Hooks are implicitly injecting whatever global state in your stateless components, so definitely not a good example of functional concepts imho.

One of the main differences in reasoning I think is how each paradigm deals with time, not in a datetime or library sense, but in the literal sense of time and causality. Does the paradigm abstract the passage of time or not? FP abstracts away time, and statements in FP are timeless, true now and in the future. That is why it ends up looking like math a bit more. Once statements in the language are sensitive to time... that means there is mutation and the line above can have a side effect on lines of code below. It's like FP is jumping a dimension and it makes statements that have to be true at all times (pure FP anyway), while mutation languages give you fine-grain control on what is being computed each unit of time.

Of course you then have a mixture of both, which many if not most modern languages have. Pure FP can be expressed in a language that supports mutation anyway, it's just a matter of how much first class support those features have. Languages like Haskell I think go so far into the abstracting of time, that they reached around and achieve something like mutation based syntax, except there is a tower of abstractions working under the hood, ensuring that it's still timeless equations which result in side effects.

What makes you think that a person with a degree in theoretical physics who is making their livelihood writing code is qualified to teach functional programming and more so address the (well justified) peculiarities of FP you are raising here?

I think you are replying to misleading title and some other article. There is no "TFA" here; it's a little game.

Iterators with a capital I are not functional.

Functions like ‘map’, and ‘fold’, and ‘zip’ are; but Iterator is not the term to describe such function.

Truth be told, me writing Iterators with a capital I comes from when I finally had this "click in my mind" moment where I got to see clearly how map & friends work, by using Rust [1] to solve a bunch of Advent of Code 2019 problems

[1]: https://doc.rust-lang.org/std/iter/trait.Iterator.html

Applications are open for YC Summer 2023

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