[HN Gopher] Learn Functional Programming Visually ___________________________________________________________________ Learn Functional Programming Visually Author : polyrand Score : 291 points Date : 2021-02-14 10:25 UTC (12 hours ago) (HTM) web link (david-peter.de) (TXT) w3m dump (david-peter.de) | austincheney wrote: | The biggest challenge with teaching functional programming is | that people tend to take the word _function_ or the concept way | to seriously. They start mandating restrictions on input /output, | what functions should be used for, and all kinds of other | unnecessary nonsense. It's like they need some sort of self | imposed guardrails to qualify making better or more common use of | functions. Like they need an official invitation before joining | the party. | | Perhaps some of that stupidity is bound to a developer's | understanding of their language at hand. Some languages are more | expensive than others. This is where the sad confused developer | mandates that functional programming must be declarative... until | you point out the languages _Red_ and _Rebol_ are functional | imperative languages. It's not some shallow wishful opinion. That | is how those languages describe themselves and it's what they | look like. | | When you take all the stupidity, assumptions, and restrictions | away functions are most universally a bag of instructions, as are | classes and various other things. Functions are unique from other | instruction bags in that they execute. That creates potential for | instruction reuse and thus portability. | | Different languages impose different restrictions on where or how | functions may present. In JavaScript functions are first class | citizens which means they can be used anywhere a primitive may be | used, which is almost everywhere. Functions can also be nested in | that language which just means subdivided layers of | portability/reuse. In this case, in a highly imperative way, | functional programming can mean programming with a mindset of | functions first, as opposed to other means of structure or | extension. Again that interpretation of functional programming | tends to make people uncomfortable as there are no restrictive | guardrails or super specific defining rules. | louthy wrote: | > They start mandating restrictions on input/output, what | functions should be used for | | Like what? You've thrown out a ton of generalisations, but | nothing here is concrete. | | > When you take all the stupidity, assumptions, and | restrictions away functions are most universally a bag of | instructions, as are classes and various other things. | | If you group all things together as a 'bag of instructions' | then there's no point in teaching functional concepts or any | paradigm's concepts for that matter. | | I am reading between the lines here, but I am assuming by | 'restrictions' you're referring to functions taking immutable | values and returning immutable values. There are sensible | reasons for this (along with referential transparency in | general) that enable function composition, which is the 'super | power' of functional programming. It isn't a requirement, it's | just good practice, and so I can understand why FP advocates | would promote it (I certainly do). | | A class can have those powers too if it is immutable, because | ultimately any class is just a set of functions with an | implicit 'this' argument, but it's often understood | differently. It doesn't seem unreasonable to promote and talk | about the differences in approach, especially in languages that | allow you to 'cheat'. | | Yes, the narrow definition of a functional language is that it | has first class functions. Clearly though there's techniques | for success within the paradigm. | | Again, it's quite hard to latch onto exactly what you're saying | here, but I don't think functions as structure is the argument | for FP (as such), it's functions that work like mathematical | functions, to leverage the centuries of knowledge of | mathematical expressions, proofs, etc. Personally, I find my | functional code much easier to understand, compose, test, and | generally have confidence in. When I compose two functions I | don't have to 'go and look inside' to see what it does first, | because they're pure and declarative. | | The declarative nature of the functions is an artefact of | following the good practice of immutable values, referential | transparency, and total functions which lead to 'honest' type- | signatures, it just happens on its own. | | I spent a reasonable part of my career in imperative-land, and | honestly I wish I'd found functional programming much earlier. | I write fewer bugs and I have more confidence in my code. And | yes, it adds constraints that are annoying sometimes, but those | constraints ultimately stop the code becoming a cognitively | difficult mass of mutation or hidden complexity. | austincheney wrote: | > You've thrown out a ton of generalisations, but nothing | here is concrete. | | That was intentional. Specifics aren't necessary for making | the point. Had I stated the specifics you were looking for I | suspect you would have focused only on that, missing the | primary point. | tempodox wrote: | > ...missing the primary point. | | Like GP, I would have to guess what your point actually is. | austincheney wrote: | _They start mandating restrictions on input /output, what | functions should be used for, and all kinds of other | unnecessary nonsense._ | jhardy54 wrote: | A specific example of what you mean would be great. More | comments quoting yourself and refusing to explain what | you mean would be not great. | eevilspock wrote: | Whether or not you're right about functional programming, your | use of "stupidity" made me think more about what kind of person | you are rather than the merits of your argument. | | In your other reply you come off as haughty or patronizing. | | One does not need high EQ or SQ to be kind. | [deleted] | MauranKilom wrote: | I had fun playing through all the challenges. But I don't think I | walked away with a better idea of functional programming. This is | closer to "learn LINQ", seeing as we're only chaining functions. | | I would be interested in seeing this expanded to include passing | functions to functions (that is, make the user build a tree of | functions, not a list). And yes, that might put you into hot | water regarding how to communicate signatures and such. | bhargav wrote: | The way this works technically is really great. Kudos to the | developer. The game itself ... I do not think it helped me learn | anything. | np_tedious wrote: | Cool game! | | Headline here might be a little grandiose. Author has "A puzzle | game inspired by functional programming" on the project's Github. | I find this more apt | franknine wrote: | This game reminds me of Infinifactory by Zachtronics | https://store.steampowered.com/app/300570/Infinifactory/ | shaneprrlt wrote: | Really cool! If you had the time/energy, this would be an | enjoyable mobile game. | auggierose wrote: | Cool game, but I don't think it is actually a good idea to see | this as "learning functional programming". | | After all, this shows some very convoluted ways of getting a | simple end result ;-) | | Also, I've only played the first few easy levels, so I guess | there will be more than "map" later on? Otherwise I would just | leave the "map" word out of it. | alisonkisk wrote: | No, it's just a misleading HN title. | cush wrote: | As a game it seems to exercise the same parts of your brain. | wodenokoto wrote: | What is the programming equivalent of stack equal columns? | | I get the map and filter operations but I can't remember ever | coming across a function like that before. | yatac42 wrote: | > What is the programming equivalent of stack equal columns? | | The game's "stack equal columns" corresponds to Haskell's | Data.List.group function: | | > import Data.List | | > group [1,2,2,3,3,3,2,1,1] | | [[1],[2,2],[3,3,3],[2],[1,1]] | julienfr112 wrote: | What about Excel ? ;) | j1elo wrote: | 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 :) | random314 wrote: | 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 | | https://www.haskell.org/tutorial/io.html | | 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. | millstone wrote: | 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. | Grustaf wrote: | > 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. | j1elo wrote: | 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... | samhh wrote: | 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. | Grustaf wrote: | 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. | pcstl wrote: | 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. | xupybd wrote: | 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. | alisonkisk wrote: | I think you are replying to misleading title and some other | article. There is no "TFA" here; it's a little game. | adamkl wrote: | 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 | gmi01 wrote: | 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 | snarkypixel wrote: | Redux in the react world is a good example of real-world | application using pure functions and functional programming | concepts. | Jestar342 wrote: | 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. | sfvisser wrote: | 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. | proc0 wrote: | 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. | logbiscuitswave wrote: | 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. | maartenh wrote: | This reminds me of the tree diagrams I wrote during the Term | Rewriting Systems course at the Vrije Universiteit [1]. | | Functional programming really started to resonate with me at that | time. Properties like confluence were very useful to understand | distributed systems algorithms later on, and e.g. how eventual | consistency plays out. | | [1] The teacher was awesome too. If you'd like to learn more | about term rewriting systems, go take a peek at his slides | http://joerg.endrullis.de/teaching/#trs (Note, just noticed that | they are behind a password. A gentle email will probably get you | the slides though :) | mettamage wrote: | Fun to see you here! We've studied together! I'm glad I'm not | the only one recommending Vrije Universiteit courses on HN, now | we're a crowd :P | | I'll send you a PM :) | alisonkisk wrote: | Since the model is an array of pillars, the visualization has a | wall is confusing. Would be better to add some space between | columns, and remove the 3D/isometric effect. | | The mathematical problems break the "visual" model. They are | harder to understand when you have to spend most of your energy | doing 8 simultaneous mental conversions to base 8 while solving. | spiralganglion wrote: | This is cool. It would be improved by adding the CSS _#controls { | user-select: none }_ (with various vendor prefixes). A bit of | refinement to how dragging is detected wouldn 't hurt either. | t0astbread wrote: | Good idea but I was able to solve most of the puzzles without | ever thinking about what my program was actually doing, | especially in the "math" levels. In the sense that I knew what | was going on, I got the concepts but I never "evaluated" the | program in my head. I just made some educated guesses based on | what I thought the patterns might turn into. Maybe that's | deliberate here but I thought that's usually not what puzzle | games want. | alisonkisk wrote: | The other problem is that it's easier to brute force the small | set of permutations of options, than to think it through. ___________________________________________________________________ (page generated 2021-02-14 23:00 UTC)