[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)