[HN Gopher] Functional programming jargon in plain English
       ___________________________________________________________________
        
       Functional programming jargon in plain English
        
       Author : mgliwka
       Score  : 471 points
       Date   : 2022-07-01 10:00 UTC (3 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | naillo wrote:
       | "A homomorphism is just a structure preserving map. In fact, a
       | functor is just a homomorphism between categories as it preserves
       | the original category's structure under the mapping."
       | 
       | Oh ok. Plain english.
        
         | psychoslave wrote:
         | Yue Shu haShou rareta
        
         | marcosdumay wrote:
         | Well, it's not nested.
        
         | eddyschai wrote:
         | Maybe if I explain what a Monad is in Plain English it'll help
         | you understand functors?
         | 
         | A monad is just a monoid in the category of endofunctors.
        
           | mypalmike wrote:
           | I think you need to explain endofunctors.
           | 
           | An endofunctor is the category containing monoids such as the
           | monad.*
           | 
           | *This is probably wrong. Please don't explain.
        
           | the_only_law wrote:
           | The closest I've come to understanding Monads was funny
           | enough, the Wikipedia page (ok so there's at least two pages
           | on Wikipedia for Monads, one in a category theory context,
           | and one in a more general programming context, the latter I
           | could actually begin to grasp). It wasn't overly full of
           | vocabulary from category theory, nor did it try to compare it
           | to taco bell menu items.
        
           | IncRnd wrote:
           | If I may also quote!
           | 
           | A monad is a special kind of a functor. A functor F takes
           | each type T and maps it to a new type FT. A burrito is like a
           | functor: it takes a type, like meat or beans, and turns it
           | into a new type, like beef burrito or bean burrito.
        
         | cratermoon wrote:
         | Best comment in this thread. The guide does a so-so job of
         | building on terms previously defined. The term accumulator, for
         | example, is not defined before use. The first appearance of it
         | is under Catamorphism, where the guide says, "A reduceRight
         | function that applies a function against an accumulator and
         | each value of the array (from right-to-left) to reduce it to a
         | single value."
         | 
         | I note, in passing, that the actual guide is just titled
         | "Functional Programming Jargon". It does not claim to be "in
         | plain English".
        
       | jtdev wrote:
        
       | rbonvall wrote:
       | Let me present this intuition I've developed.
       | 
       | * You have a producer of Cs, then you can turn it into a producer
       | of Ds by post-processing its output with a function g: C - D.
       | 
       | * You have a consumer of Bs, then you can turn it into a consumer
       | of As by pre-processing its input with a function f: A - B.
       | 
       | * You have something that consumes Bs and produces Cs, then you
       | can turn it into something that consumes As and produces Ds using
       | two functions f: A - B and g: C - D.
       | 
       | With pictures: http://mez.cl/prodcons.png
       | 
       | If you understand that, you understand functors:
       | 
       | * producer = (covariant) functor;
       | 
       | * consumer = contravariant functor;
       | 
       | * producer-consumer = invariant functor;
       | 
       | * post-processing = map;
       | 
       | * pre-process = contramap;
       | 
       | * pre- and post-processing = xmap (in Scala), invmap (in
       | Haskell);
       | 
       | * defining how the pre- and post-processing works for a given
       | producer or consumer = declaring a typeclass instance.
       | 
       | It doesn't mean that "a functor _is_ a producer ", but the
       | mechanics are the same.
        
       | ncmncm wrote:
       | This is more helpful than anything I have ever encountered on the
       | topic.
       | 
       | Comments:
       | 
       | 1. It should explain map somewhere before it is used.
       | 
       | 2. For the more abstruse and abstract concepts, a comment
       | suggesting why anybody should care about this idea at all would
       | be helpful. E.g., "A is just a name for what [familiar things] X,
       | Y, and Z have in common."
       | 
       | 3. It goes off the rails halfway through. E.g. Lift.
        
         | sanderjd wrote:
         | Expanding on your #1, I think they could use some more
         | definitions. As you say, they use "map" in its functional
         | programming sense before defining it, but I think more
         | confusing is this one:
         | 
         | > _A category in category theory is a collection of objects and
         | morphisms between them._
         | 
         | What is a "morphism"?
         | 
         | I think this is a great starting point though, which could use
         | some expansion.
        
           | ncmncm wrote:
           | Ja, that "morphism" bit matches my #3.
        
       | goto11 wrote:
       | Pet peeve: The word "just" when used to gloss over something with
       | the author don't know how to explain. Using "just" shift the
       | burden from the author to the reader, since it signals it is the
       | readers fault if they don't understand.
       | 
       | > A homomorphism is just a structure preserving map. In fact, a
       | functor is just a homomorphism between categories as it preserves
       | the original category's structure under the mapping.
       | 
       | How about removing the "just":
       | 
       | > A homomorphism is a structure preserving map. A functor is a
       | homomorphism between categories as it preserves the original
       | category's structure under the mapping.
       | 
       | Much clearer. Although most readers would now ask what
       | "structure" and "structure preserving" means, since this is never
       | explained.
        
         | josu wrote:
         | Be the change you want to see in the world haha
         | 
         | https://github.com/hemanth/functional-programming-jargon/pul...
        
         | bjarneh wrote:
         | > The word "just" when used to gloss over something with the
         | author don't know how to explain.
         | 
         | Never thought of that before, but it's certainly true. Always
         | hated when we got cryptic explanations for the difficult
         | things, and elaborate explanations for the stuff everyone
         | understood anyway at the university. I guess professors have to
         | explain things they don't fully understand from time to time
        
         | cinntaile wrote:
         | This is left as an exercise to the reader.
        
           | minraws wrote:
           | Just to be clear, that's quite literally the Wikipedia
           | definition.
           | 
           | > In algebra, a homomorphism is a structure-preserving map
           | between two algebraic structures of the same type (such as
           | two groups, two rings, or two vector spaces).
           | 
           | Not sure if this is rude but many definitions there seem a
           | bit, not plain English.
           | 
           | I am assuming we are aiming for something close to ELI5 if
           | the title says plain English.
           | 
           | Ofc that could not be what the author intended and is just
           | but that's how inferred the title.
           | 
           | I will see if I can find time to improve and send some PRs
           | for the ones that are in deep need of simplification,
           | hopefully OP is open to discussing changes.
           | 
           | Also like Arity, Arity is not just for functions, it can
           | sometimes be interchanged with Rank and apply to even Types.
           | higher ranked types. higher arity types... I do understand
           | they are not something most people like, because of their
           | issues but that's not a complete definition so I assumed it
           | was for the means of simplifying to explain to beginner
           | programmers. [reference to issues with HRTs](https://www.scie
           | ncedirect.com/science/article/pii/S016800729...)
           | 
           | Again this is not meant to be rude to the author, just
           | hopefully the title could be better formed to explain the
           | intent of the work. Or my opinion might be minority and we
           | can decide against it as well ofc.
        
         | mjburgess wrote:
         | The former means: all Hs are SMPs ; the latter may also mean:
         | some Hs are SMPs.
         | 
         | The former is clearer. Adjust your understanding of `just`,
         | it's definition 4a at
         | https://www.britannica.com/dictionary/just
        
         | marcosdumay wrote:
         | As a hint, any time you read "just" in mathematics, replace it
         | with "exactly". That may make it clearer.
        
         | saithound wrote:
         | Mathematicians use "just" with a specific meaning: it is not
         | used to gloss over something that the author doesn't know how
         | to explain. It has a purpose, useful for mathematically trained
         | readers.
         | 
         | For suc a reader, "a homomorphism is just a structure
         | preserving map" makes it clear that "homomorphism" and
         | "structure-preserving map" can be used interchangably, and that
         | by understanding one of the concepts, you'll immediately
         | understand the other as well.
         | 
         | When you got rid of the word "just", you got rid of this
         | connotation and changed the meaning of the sentences.
         | 
         | E.g. the sentence "a functional is a linear transformation" is
         | correct; but not all linear maps are functionals, so writing "a
         | functional is just a linear transformation" would be plain
         | wrong in a mathematical setting.
        
           | 8note wrote:
           | I don't understand who the audience for this glossary is.
           | 
           | Math students coming from another discipline?
           | 
           | Only some people will understand the technical meaning of
           | "just" as intended
        
           | plasticchris wrote:
           | Sure, but the title does say plain English so this would be
           | the sort of thing the author is trying to avoid. If that's
           | the meaning just write all a are b.
        
             | saithound wrote:
             | While I agree that the English used in the repo could be
             | plainer, that's not remotely the same thing as "using
             | 'just' to gloss over something that the author doesn't know
             | how to explain", which was the complaint that goto11 made.
        
           | nabla9 wrote:
           | Both you and goto11 make a good point.
           | 
           | What is needed is "Mathematical English in plain English."
        
           | minraws wrote:
           | This has not been true in my experience, as someone who is
           | used to talking to a mathematician during my academic life (a
           | bit). They prefer to not use words like "just X".
           | 
           | They generally reply in definite statements, "this is
           | undecidable", "this is an example of X", "this can't be done
           | without Y", they rarely say. "X is just Y", they would
           | probably say, "X is Y".
           | 
           | The "just" implies some form of detail that might be missing
           | in the relation generally. Even my mathematical text books of
           | pretty advanced topics rarely used "just".
           | 
           | Again, what you say is most likely true when math people talk
           | amongst themselves but I don't think they do so with other
           | non math people. I was in compsci.
        
             | mjburgess wrote:
             | "just" is used across technical academia (including
             | philosophy) to mean "nothing over and above"
        
           | lachenmayer wrote:
           | That would be an extremely good thing to explain in the
           | introduction. I feel like this kind of very culturally-
           | specific usage of everyday words is what makes math/CS papers
           | so impenetrable for many people.
           | 
           | The word "easy" is another example: saying "it is easy to
           | show X" (just?) means that X can be derived from the already
           | stated theorems in a more-or-less mechanical way without
           | having to introduce new concepts. It does not in any way
           | suggest that deriving this will be "easy" for a student
           | reading the paper.
           | 
           | (Of course the most challenging "easy" parts are best left as
           | an exercise for the reader anyway...)
        
           | jasode wrote:
           | _> Mathematicians use "just" with a specific meaning: it is
           | not used to gloss over something that the author doesn't know
           | how to explain. It has a purpose, useful for mathematically
           | trained readers._
           | 
           | Based on the author's public profile, I'm not convinced the
           | author is a mathematician writing _"... is just ... "_ as
           | rigorous formalizations for a math-trained audience.
           | 
           | Instead, the _" is just"_ phrases are innocently slipping
           | into explanations as a subconscious verbal tic caused by the
           | The Curse of Knowledge. My previous comment on that
           | phenomenon: https://news.ycombinator.com/item?id=28256522
           | 
           | (Also, as a sidebar followup to your comment, Wikipedia's
           | page about homomorphism
           | (https://en.wikipedia.org/wiki/Homomorphism) has this as the
           | first sentence: _" In algebra, a homomorphism is a structure-
           | preserving map ..."_
           | 
           | I'm guessing that a hypothetical edit to _" a homomorphism is
           | _just_ a structure-preserving map"_ -- in an attempt to add
           | more refinement and precision to the definition... would be
           | rejected and reverted back by other mathematicians.)
        
       | jacquesm wrote:
       | "Category
       | 
       | A category in category theory is a collection of objects and
       | morphisms between them. In programming, typically types act as
       | the objects and functions as morphisms."
       | 
       | Much clearer now...
        
       | mjburgess wrote:
       | These definitions don't really give you the idea, rather often
       | just code examples..
       | 
       | "The ideas", in my view:
       | 
       | Monoid = units that can be joined together
       | 
       | Functor = context for running a single-input function
       | 
       | Applicative = context for multi-input functions
       | 
       | Monad = context for sequence-dependent operations
       | 
       | Lifting = converting from one context to another
       | 
       | Sum type = something is either A or B or C..
       | 
       | Product type = a record = something is both A and B and C
       | 
       | Partial application = defaulting an argument to a function
       | 
       | Currying = passing some arguments later = rephrasing a function
       | to return a functions of n-1 arguments when given 1, st. the
       | final function will compute the desired result
       | 
       | EDIT: Context = compiler information that changes how the program
       | will be interpreted (, executed, compiled,...)
       | 
       | Eg., context = run in the future, run across a list, redirect the
       | i/o, ...
        
         | jmgimeno wrote:
         | Yes, but you're relying on the undefined concept of context.
         | How do you define context?
        
           | mjburgess wrote:
           | "The idea" practically, is whatever resolves the
           | polymorphism. So context is a compiler function from
           | syntax->semantics.
           | 
           | Eg., `+` is polymorphic, `1 + 1` and `"1" + "1"`... the
           | _context_ is whatever implicitly resolves `+` to `ADD` or to
           | `CONCAT`.
           | 
           | The utility of these ideas is, in practice, just they provide
           | a syntax for different kinds of polymorphism. Eg., for
           | monads, we're basically just telling the compiler to change
           | its implementation of `;`
        
         | shikoba wrote:
         | > Functor = context for running a single-input function
         | 
         | No a functor is a "function" over types that can transport the
         | arrows:
         | 
         | (A -> B) -> (F A -> F B) for a covariant functor
         | 
         | (A -> B) -> (F B -> F A) for a contravariant functor
         | 
         | With the sum and product there is also the exponential:
         | 
         | B^A = functions from A to B
        
           | stillkicking wrote:
           | This explanation is useless imo because it expects the reader
           | to already understand the weirdest part:
           | 
           | "If I have a function A -> B, how could I possibly get
           | something that goes in the direction F B -> F A out of it?"
           | 
           | The answer to this is: given e.g. a function that accepts a
           | B, i.e. `B -> ...` you can compose it with `A -> B` on the
           | _input side_, to get a function that accepts an A, i.e. `A ->
           | B` (+) `B -> ...` = `A -> ...`.
           | 
           | Once you've managed to get that across, you can start talking
           | about contravariant functors. But expecting people to just
           | intuit that from the condensed type signature is pedagogical
           | nonsense.
        
             | shikoba wrote:
             | Saying without examples is a pedagogical nonsense, I can't
             | argue, because I agree.
             | 
             | But if I provide the two typical examples Hom(A,) and
             | Home(,A) and how they transport the arrows it starts to
             | click.
             | 
             | There is also List which is a covariant functor. The stupid
             | Home(unit,) which is the "identity" functor.
             | 
             | I could also add Hom(Bool,) which is the pair functor, ie
             | Hom(Bool,A) is a tuple in AxA. A->AxA (or A->Him(Bool, A))
             | is a covariant functor.
             | 
             | Etc. Examples are the keys to understand the idea.
        
           | mjburgess wrote:
           | In my simple language, `F` is that context. And (A->B) is a
           | single-argument function.                  // Int -> Float
           | oneArgFn(x) = x + 1.1             // List of Int -> List of
           | Float        ctxOneArgFn(xs) = ListFunctor(oneArgFn, xs)
           | //ie., map()
        
             | reuben364 wrote:
             | Single-argument doesn't capture the difference between
             | functor and applicative.                 ex1 :: Functor f
             | => f (Int, Int) -> f Int       ex1 = map (uncurry (+))
             | 
             | Applies a multi-argument function within a functor. What
             | applicative allows you do is take a product of contexts to
             | a context of products, and lift a value to a context.
             | pure :: a -> f a       zip :: (Applicative f) => (f a, f b)
             | -> f (a, b)
             | 
             | This can then be used to make ex1 into a multi-argument
             | function of contexts, which is not the same as (uncurry
             | (+)) being a multi-argument function                 ex2 ::
             | (Functor f) => (f Int, f Int) -> f Int       ex2 = ex1 .
             | zip
        
               | mjburgess wrote:
               | Sure, it's a particular interpretation of `(f a, f b) ->
               | f (a, b)`                   (a, b) is an a -> b
               | (f a, f b) is an f a -> f b
               | 
               | Applicative, over an above this, is really just useful
               | when you have (f a, f b, f c, ..)
        
             | shikoba wrote:
             | You're just reducing my idea to a specific case. You missed
             | the generalized idea.
        
           | init0 wrote:
           | Send a PR to fix it!
        
             | shikoba wrote:
             | There are so many things to fix. And they should have use
             | coq as default language.
        
         | HelloNurse wrote:
         | A product type, named after Cartesian product, _contains_ other
         | objects of various types, but it is none of A, B or C itself.
         | 
         | If types A, B and C have respectively a, b and c distinct
         | values, their sum type has a+b+c values (each value of each
         | type is allowed) and their product type has abc values (the
         | part of the value that belongs to each type can be chosen
         | independently).
        
         | mgaunard wrote:
         | Currying is just systematic partial function application for
         | each argument.
        
         | yowlingcat wrote:
         | I find your list a lot more helpful (and succinct) than the
         | linked repo in the thread topic. Kudos! Perhaps you should make
         | your own repository -- I would upvote it!
        
         | init0 wrote:
         | Send a PR to the repo!
        
         | stingraycharles wrote:
         | I completely understand what you're saying, but assuming that
         | this guide is aimed at people entirely unfamiliar with these
         | concepts, I'm not sure whether these "ideas" provide any
         | meaningful explanation to them.
         | 
         | Demonstrating by example what e.g. currying actually looks like
         | is much more powerful, at least from my point of view. In that
         | regard, I'm actually pleasantly surprised this guide does a
         | very good job at that.
        
           | mjburgess wrote:
           | Currying is one of those cases where the code _is_ the
           | explanation
           | 
           | I think in many cases this isnt right, eg., Monads. The
           | reason flatMap() "flattens" is just that "flattening" is
           | really just sequencing, denesting the type using a function
           | requires a sequenced function call: f(g(..))
           | 
           | This applies to many of these "functional design patterns"...
           | theyre just ways of expressing often trivial ideas (such as
           | sequencing) under some constraints.
        
             | ncmncm wrote:
             | We need an explanation why we should care about support for
             | currying. Where it is really just to support variadic
             | argument lists, it is a big hammer for a little problem.
        
               | stingraycharles wrote:
               | And precisely because of the code sample, it should be
               | obvious that currying is _not_ the same as variadic
               | function arguments.
               | 
               | Instead, it allows for very concise partial function
               | application, as demonstrated by the code. I can just call
               | any function with a subset of its arguments, and it
               | automatically returns a "new function" which you can call
               | with the remainder of the arguments. It allows you to
               | reason about calling functions in a different way.
               | 
               | Currying is one of those concepts done very well in
               | languages such as Haskell (not a coincidence, as both
               | derive their name from Haskell Curry).
               | 
               | But saying it's a "big hammer to implement variadic
               | function arguments" is like saying that pattern matching
               | is a big hammer to implement a switch statement. Yes, it
               | provides that functionality, but also much more in a very
               | elegant manner.
        
               | ncmncm wrote:
               | Saying _" it allows for very concise partial function
               | application"_ does nothing but repeat the definition. It
               | does not, in particular, offer any reason to want that.
               | What is so special about the first argument, that I want
               | to fix it? Why not the third? Why is what I do to fix the
               | third not just as good for the first?
               | 
               | Pattern matching is a good example of a language feature
               | included because they could not figure out how to provide
               | features expressive enough to be composed to implement
               | the feature in a library.
        
               | chowells wrote:
               | In a language like Haskell, pattern matching was
               | explicitly chosen to be a primitive operation. It's not
               | that there's no way to put it in a library; it's that it
               | was chosen to be one of the small set of ideas everything
               | else is described in terms of. Along with allocation and
               | function application, you've got the entirety of
               | Haskell's evaluation model. (Note: not execution model.
               | That needs a bit more.) Having such a small evaluation
               | model probably should be taken as evidence the primitives
               | were chosen well.
        
               | a1369209993 wrote:
               | > Note: not execution model. That needs a bit more.
               | 
               | Actually... not really? You need the foreign function
               | interface to have anything useful _to_ execute, but
               | (unless you 're talking about something else?) the
               | execution _model_ is basically just a State monad
               | carrying a unique magic token, built on top of the same
               | evaluation model as everything else.
        
               | chowells wrote:
               | The execution model needs _something_ that actually
               | drives execution. There needs to be something that
               | explains how IO actions are actually run. The state
               | approach kind of works until you need to explain multiple
               | threads, then it falls over.
               | 
               | Edward Kmett did some work to describe IO as an external
               | interpreter working through a free monad. That approach
               | provides very neat semantics that include multiple
               | threads and FFI easily.
               | 
               | But IO needs something to make it go, and that something
               | needs capabilities that aren't necessary for the
               | evaluation model.
        
               | a1369209993 wrote:
               | > The execution model needs _something_ that actually
               | drives execution.
               | 
               | Er, yes: specifically, execution is drivenby trying to
               | pull the final RealWorld token out of a expression along
               | the lines of `runState (RealWorld#) (main)`, which
               | requires the evaluation of (the internal RealWorld ->
               | (RealWorld,a) functions of) IO actions provided by FFI
               | functions (hence why you need FFI to have anything useful
               | (or more accurately, side-effectual) to execute).
               | 
               | > until you need to explain multiple threads
               | 
               | I don't. It's a terrible idea that's effectively the
               | apotheosis of premature (and ill-targeted) optimization
               | as the root of all evil.
        
               | Arrrlex wrote:
               | Currying support is orthogonal to how function arguments
               | work. Some languages (e.g. OCaml according to this
               | question[1]) combine named parameters with currying,
               | allowing partial application with any of the function's
               | arguments.
               | 
               | [1] https://stackoverflow.com/questions/3015019/is-there-
               | a-progr...
        
               | jerf wrote:
               | I'm not trying to dodge your question, but the answer to
               | your question is that until you work with it for a while
               | you're not going to understand it. Any blog-sized, bite-
               | sized snippet isn't impressive. You have to work with it
               | for a while.
               | 
               | I speak many computer languages, and one of the ways I
               | measure them is, "what do I miss from X when using Y?"
               | The answers will often surprise you; the thing you'd
               | swear up and down you'd miss from X you may never think
               | of again if you leave the language, and some feature you
               | hardly consider while you're in the thick of programming
               | in X may turn out to be the thing you miss in every other
               | language for the rest of your life. For me, one of the
               | things I deeply miss from Haskell when programming
               | elsewhere is the fluidity of the use of partial function
               | application through the currying syntax. I see so many
               | people trying to force it out of Haskell into some other
               | language but there just isn't any comparison to the
               | fluidity of                   map someFunc . filter other
               | . map (makeMap x y) $ userList
               | 
               | Currying enables that syntax. If you don't see how, I'm
               | not surprised. Sit down and try to write a syntax
               | extension for an Algol-descended language that makes it
               | work that well. Be honest about it. Run some non-trivial
               | expressions through it. What I show above you should
               | consider the _minimum_ level of expression to play with,
               | not the maximum. If you pick something like Python to
               | work in, be sure to consider the interaction with _all_
               | the types of arguments, like positional, keyword,
               | default, etc. It can absolutely be done, but short of re-
               | importing currying through the back door I guarantee the
               | result is a lot less fluid.
               | 
               | The question about "what is special about the first
               | argument" is backwards. The utility of the first argument
               | is something you choose at _writing_ time, not _use_
               | time. The reason why map 's first argument is the
               | function to map on and the second is the list to map over
               | is nothing more and nothing less than most of the time,
               | users of map use it as I show above. There's no deep
               | mathematical or group theory reason. If you don't like it
               | there are simple functions to change the orders around,
               | and the goal of picking function argument orders is just
               | to minimize the amount of such functions in the code.
               | Nothing more, nothing less.
        
               | skybrian wrote:
               | That's an example of why Haskell code is often hard to
               | read, and why I'm glad this _isn 't_ available in other
               | languages. Why not write out the callback given to map
               | using a let block? Then you can give meaningful names to
               | intermediate values so it's easier to see how the
               | pipeline works.
               | 
               | (Though, functional programmers would probably pass up
               | the opportunity and use one-letter variable names.)
        
               | Iceland_jack wrote:
               | The feature is not called currying but partial
               | application, it is very nice and intuitive.
        
               | lgas wrote:
               | Is this what you mean?                   let f = makeMap
               | x y         in map someFunc . filter other . map f $
               | userList
               | 
               | I suspect not as it certainly doesn't seem to improve the
               | situation. Perhaps you could elaborate?
               | 
               | Edit to add: I was focused on the "write out the callback
               | given to map using a let block" part and not the
               | meaningful name part, but that's perhaps what's confusing
               | about this to me, as (makeMap x y) seems like the most
               | clear name possible here, what else could you do? This?
               | let mapOfXy = makeMap x y         in map someFunc .
               | filter other . map mapOfXy $ userList
               | 
               | It only obscures things.
        
               | ncmncm wrote:
               | OK, thank you. The key seems to be that argument lists
               | for functions in a language with easy currying are
               | carefully designed so as to make currying maximally
               | useful.
        
               | jstanley wrote:
               | Couldn't I "curry" a function                   f(x,y)
               | 
               | to "partially apply" it on x=3 with just:
               | function(y) { return f(3,y); }
               | 
               | ?
               | 
               | And then I've "partially applied" f. Is this what
               | currying is?
               | 
               | The syntax I posted is ambivalent about which arguments
               | you're partially applying, isn't that superior to only
               | being able to provide the first argument?
        
               | Jtsummers wrote:
               | Currying is turning a function with arity n into a
               | sequence of unary functions.                 f(x,y) = ...
               | // arity 2       f = \x -> \y -> ... // sequence of two
               | unary functions       f x y = ... // more compact
               | representation of the above
               | 
               | Regarding partial application, your JS (?) example is
               | basically what happens under the hood with Haskell, but
               | without the ceremony:                 f x y = ...
               | fByThree = f 3       fByThree y = f 3 y
               | 
               | Those last two are equivalent, but you don't have to
               | include the _y_ parameter explicitly, because _f 3_
               | returns a function that expects another parameter (like
               | the function you wrote out explicitly).
               | 
               | And the Haskell version is more general, since it doesn't
               | require a unique function to be written for each possible
               | partial application. Of course, you can do this in
               | languages with closures:                 function fByX(x)
               | {         return y => f(x,y);       }       fByThree =
               | fByX(3);
               | 
               | But in Haskell that extra function isn't needed, it's
               | just already there and called _f_. Regarding your last
               | statement, there are also combinators in Haskell that
               | allow you to do things like this:
               | fXbyThree = flip f 3       // equivalent to:
               | fXByThree x = f x 3       // JS       function
               | fXByThree(x) { return f(x,3); }       // or
               | function fXByFixedY(y) { return x => f(x,y); }
               | fXByThree = fXByFixedY(3);
               | 
               | So I'm not sure it's _strictly_ superior, it is more
               | explicit though.
        
               | jstanley wrote:
               | Thanks!
        
             | urxvtcd wrote:
             | While I _think_ I understand monads on some rudimentary
             | level through how join and bind operate, your "just
             | sequencing" doesn't tell me anything. And this is a problem
             | with a lot of these texts. Maybe that's trivial to the
             | writers, but it makes me feel even dumber when I cannot
             | understand a concept I already understand, lol.
        
               | dllthomas wrote:
               | A big problem with "just sequencing" is that there are a
               | lot of ways of sequencing that either don't require the
               | complexity of a monad or for which the monad interface is
               | insufficient.
        
               | lgas wrote:
               | The former is probably uncontroversial but I'd love to
               | see some examples of the latter since my understanding
               | was that monads are essentially the generalization of
               | sequentiality.
        
               | dllthomas wrote:
               | One obvious place to look is things that are almost a
               | monad but can't be lawful and which might nonetheless be
               | useful. An example that comes to mind is trying to use
               | Set as a monad (for nondeterminism like the list monad,
               | but with deduplication), which you can't do for some
               | potentially avoidable technical reasons (it would have to
               | be restricted to things you can Ord) but more importantly
               | Set can't be a monad because Set can't be a functor,
               | because `x == y` does not actually imply that `f x == f
               | y` (even for reasonable definitions of Eq), so `fmap (f .
               | g)` might not be equivalent to `fmap f . fmap g`.
        
               | lgas wrote:
               | I thought it was the case that you can't implement the
               | Monad type class using the built in Data.Set
               | implementation of Sets but there's no reason in principle
               | why you couldn't build a Set Monad that works that way,
               | right? Perhaps I am mistaken so I will investigate
               | further.
        
               | dllthomas wrote:
               | There _is_ a reason in principle that you can 't build a
               | Set Monad that works that way: it violates the functor
               | laws.
               | 
               | In order to be a functor, you need `fmap (f . g) == fmap
               | f . fmap g`.
               | 
               | The problem is that some functions (for instance,
               | Data.Set.showTree) can produce different results for two
               | values that compare equal.
               | 
               | For instance, imagine we have a set containing (only) the
               | lists `[1,2]` and `[2,1]`; let's call it s. How many
               | elements are in `fmap (Data.Set.showTree .
               | Data.Set.fromList) s`? Two, because the result of
               | fromList winds up being order dependent _in the structure
               | of the internal tree_ , even though both Sets represent
               | the same set of values. On the other hand, how many
               | elements in `fmap showTree . fmap fromList`? Just one,
               | because the Set has a chance to "see" the output of
               | fromList and notice that they are equal according to Eq.
               | 
               | Does this violation of the functor laws matter? Maybe;
               | likely not; it depends on your use case.
               | 
               | But mathematically it means that the thing we are working
               | with is not a functor, and so the thing we are working
               | with is also not a monad (as all monads are functors).
        
               | shikoba wrote:
               | I prefer to say that show tree violates the abstraction.
               | You can have s1=s2 but not f(s1)=f(S2). So f (show tree)
               | is not a real function (or = is not a real equal). But
               | showtree is a debug function, it doesn't count. It's like
               | saying in C that a=13 and b=13 isn't a real equality
               | because &a and &b are not equal. There is the underlying
               | structure and the structure after the equivalence. You
               | have to know of what you're talking.
        
               | lgas wrote:
               | Looks like https://hackage.haskell.org/package/set-monad
               | is an example.
        
               | pdpi wrote:
               | This is one of those things where looking at the type
               | signature hard enough eventually gives the game away, but
               | most writing on it sucks:                   bind :: m a
               | -> (a -> m b) -> m b
               | 
               | Because that function in the middle takes an `a`, your
               | implementation of `bind` needs to be able to take an `m
               | a` and pull an `a` out of it, which means it also has to
               | evaluate however much of `m` is needed to actually get to
               | that `a`.
               | 
               | Because that function in the middle returns an `m b`,
               | binding again with a function `b -> m c` requires you to
               | pull `b` out of `m b`, which in turn forces pulling an
               | `a` out of `m a` to make progress. This is where you
               | force sequentiality -- you can only evaluate the `m` in
               | `m b` after you've evaluated the `m` in `m a`
        
               | samiskin wrote:
               | This makes a lot more sense than anything I've read about
               | this in the past, thanks for the explanation!
        
               | pdpi wrote:
               | Thanks, that's reassuring. I've long been frustrated by
               | just how bad monad posts are in general, and been meaning
               | to write something up about it that makes it clearer.
               | It's good to know that I'm at least going in the right
               | direction :)
        
               | skybrian wrote:
               | Caveat: there is the trivial case of calling the middle
               | function zero times. Which does happen (in the case of a
               | Maybe type) but presumably any useful code needs to be
               | able to call the function sometimes.
        
           | cratermoon wrote:
           | Assuming that this guide is aimed at people entirely
           | unfamiliar with these concepts, I think it fails to explain
           | the concept. Yes, it is plain English, but it is not _simple_
           | or _common_ English, and it 's mostly code examples. I'm
           | familiar with the concepts, but not fluent, and functional
           | programming jargon I already knew is not clearer to me now
           | than it was before I read it.
           | 
           | Good sample code, though. It only required me to look up a
           | handful of things I wasn't already familiar with.
        
             | b3morales wrote:
             | I agree, and not just the English. There is use of
             | particular notation that does not explain anything unless
             | you already know what it means:
             | 
             | > f is a morphism from a -> b, and g is a morphism from b
             | -> c; g(f(x)) must be equivalent to (g * f)(x)
             | 
             | If I don't already understand (g * f)(x) this is not
             | helpful at all. This other one especially jumped out at me
             | (perhaps because I've personally never seen this "bent
             | equals sign" [?] before):
             | 
             | > A functor must adhere to two rules:
             | 
             | > Preserves identity
             | 
             | > object.map(x => x) [?] object
             | 
             | What does that sign [?] mean? If I don't know, I am no
             | closer to understanding functors. And the sign is not
             | explained anywhere in the document.
        
           | wawjgreen wrote:
        
         | irrational wrote:
         | What is a unit?
         | 
         | What does it mean to join together units?
         | 
         | What is a context?
         | 
         | What is a single input function? A function with a single
         | parameter?
         | 
         | Does multi input mean multiple parameters?
        
       | AtNightWeCode wrote:
       | Oneof? Discrete data? Fuzzy logic?
        
       | ufo wrote:
       | I get why they chose to do this in Javascript, but I can't help
       | but feel it's an awkward choice. Many of the examples (e.g.
       | currying) look unnatural in javascript.
       | 
       | https://github.com/hemanth/functional-programming-jargon
        
       | k__ wrote:
       | I like it.
       | 
       | Could need a bit of clean up. Some points could need more
       | explanation, simpler examples, and every point could follow the
       | same structure.
       | 
       | But for a beginner, I think it's a pretty starting point.
        
       | _benj wrote:
       | Without being very versed in FP and having only read the first
       | two (arity, HFO) this seems super helpful!!
       | 
       | Even if imperfect and I need to research further, this glossary
       | provides a way to attach new knowledge to existing one.
        
       | Linda703 wrote:
        
       | mgaunard wrote:
       | Looked at first one (arity), saw "argument" when what was
       | actually meant was "parameter", and therefore dismissed the
       | document.
       | 
       | If you want to make a glossary, at least try to be precise.
        
         | mtreis86 wrote:
         | They said 'a function takes arguments', which is correct. The
         | arguments are passed into the function, aligning to and being
         | bound to the function's parameters. So arity applies both to
         | arguments the function can take, and the parameters the
         | function has.
        
           | mgaunard wrote:
           | The way it's phrased and the examples makes it clear whoever
           | wrote this didn't understand the distinction.
        
       | ww520 wrote:
       | I thought this guide is great. Not sure why people are upset with
       | it. It's not the be all end all definite guide to the topic, but
       | it definitely helps.
       | 
       | I especially like the examples given that remove ambiguity in
       | explaining the concepts.
        
       | singaporecode wrote:
       | All these niche functional programming languages are an exercise
       | in pseudo intellectualism
       | 
       | Give me an object oriented language any day. The world is made of
       | state and processes, (modern niche) functional programming goes
       | too far to derecognise the value of state in our mental models
       | 
       | The good thing about functional programming is stressing to avoid
       | side effects in most of the code and keep it localised in certain
       | places...
        
         | 62951413 wrote:
         | I can relate to your sentiment but calling it " _pseudo_
         | intellectualism " is a step too far in my opinion. The math
         | behind FP is legit. Like Programming Language Theory it can
         | teach you interesting abstractions. And useful basic things
         | like how most collections you use are monoids, map/flatMap,
         | etc.
         | 
         | On the other hand, the original Design Patterns book was
         | published in 1994. I'm still waiting for its FP equivalent.
        
         | ratww wrote:
         | It's kinda funny, because you could say exactly the same about
         | object-oriented programming as a discipline.
         | 
         | In functional programming the jargon might be foreign, but they
         | correspond with the math they came from. You also have clear
         | rules and clear situations where you can apply all those
         | things.
         | 
         | In object orientation, however, we have mostly made-up jargon
         | (from patterns and from SOLID), the "rules" for the application
         | of those are completely fuzzy, arbitrary and broken most of the
         | time, and even the categorisation of those is mostly made-up.
         | It's pseudoscientific-mumbo-jumbo compared to Monads and other
         | FP silly-named stuff.
        
         | globalise83 wrote:
         | I guess you could also say that the world is made of state,
         | state transitions and state derivations, and functional
         | programming does a great job of making the latter two reliable.
        
         | ncmncm wrote:
         | Every _anything_ -oriented language amounts to wankage.
         | 
         | The world is a complicated place with complicated problems.
         | Complicated problems are always solved by splitting them into
         | different sub-problems, each routinely of radically different
         | character than the outer problem, other sub-problems, or its
         | own sub-sub-problems.
         | 
         | So, a language "oriented" for any one of those is a terrible
         | choice for others. To solve any whole problem, your language
         | should support all the styles that might be useful. Often, a
         | sub-problem falls to a style combining a little of this style
         | and a little of that. Styles should not be straitjackets.
         | 
         | Generally, it is better if the language is powerful and
         | expressive enough that support for a style is not built in, but
         | can be provided by a library. Any fancy built-in feature is
         | always an admission that the core language wasn't strong enough
         | to express it in a library.
         | 
         | That is why weak languages so often have fancy core features
         | (e.g. dictionary): without, you would be left with no support.
         | This should make us suspicious of a "match" feature.
         | 
         | A more powerful language lets you pick from variations on the
         | fancy feature in a library or libraries. And, the library might
         | define a new style useful for the sort of problems the library
         | is designed for.
        
         | krageon wrote:
         | > The world is made of [...]
         | 
         | Either define concretely what the world is made of (i.e.
         | particles and what they do), or don't use this sentence.
         | Currently you just say "wow this is so abstract, it's actually
         | <something else that's also abstract>". Turns out neither
         | paradigm has anything to do with real life, they have their own
         | niches and their own place within different contexts.
        
         | rswail wrote:
         | Functional programming is actually mathematics based on lambda
         | calculus.
         | 
         | Imperative programming isn't.
         | 
         | OOP is a failed metaphor, unless you use composition, not
         | inheritance, even then, the actual basis for OOP was about the
         | messages between objects, not the internals.
         | 
         | > The world is made of state and processes
         | 
         | No, the world is made of objects that have state and messages
         | (events) between them.
        
           | jimbob45 wrote:
           | The lambda calculus is an entirely arbitrary way to organize
           | things in math. It's not based on nature or truth at all.
           | 
           | The real problem, though, is that FP doesn't do anything
           | well. It's never the fastest method of programming, which
           | means that it needs to excel in some other way for its
           | proponents to be right about it. Is it the most maintainable?
           | Maybe if you have zero side effects but then any paradigm
           | would be in that case. Once you introduce state, it becomes a
           | nightmare to maintain, unlike OOP. It's certainly not the
           | most readable.
        
             | ebingdom wrote:
             | > The lambda calculus is an entirely arbitrary way to
             | organize things in math. It's not based on nature or truth
             | at all.
             | 
             | Lambda calculus, category theory, and logic are essentially
             | 3 sides of the same coin (the Curry-Howard-Lambek
             | correspondence). The rules of lambda calculus match those
             | of natural deduction. It runs quite a bit deeper than
             | you're suggesting here. It's not just some arbitrary
             | formalism.
        
               | dboreham wrote:
               | Glad to see these comments because the parent's "it's
               | math therefore from a deity, and much more correct than
               | your grubby computer stuff" is so often trotted out. It
               | turns out that there's no directionality to the
               | relationship between mathematics and computers -- they're
               | the same thing and one can be transformed into the other.
               | e.g. Lambda Calculus is just a kind of VM someone came up
               | with that can be used to model certain structures. Same
               | for Category Theory, and same for Logic. So you might as
               | well say that Lambda Calculus is derived from IBM 360
               | assembler language than the other way around.
        
           | garethrowlands wrote:
           | There are limits on what lambda calculus can model though.
           | For example, it doesn't model IO very well. So, these days,
           | lambda calculus is only one of the parts of maths that
           | informs functional programming.
        
             | [deleted]
        
         | lordnacho wrote:
         | Doesn't every mainstream language these days allow you to pick
         | what style you want according to the situation?
        
           | ncmncm wrote:
           | That practically defines mainstream language, alongside
           | having been blessed with a non-repeatable miracle.
           | 
           | But C, Java, and Go don't.
        
       | ris wrote:
       | And no explanation of fixed points.
        
       | Jemm wrote:
       | As someone who learned coding in the days of Pascal and Fortran;
       | can I just say: WTF and why!
        
       | Latty wrote:
       | Lists like this tend to be a bit overwhelming without context,
       | because a definition can often seem to focus on things that don't
       | make sense if you don't understand the use case, even if you
       | understand the words.
       | 
       | Even if you've read the definition of functor first
       | 
       | > Lifting is when you take a value and put it into an object like
       | a functor. If you lift a function into an Applicative Functor
       | then you can make it work on values that are also in that
       | functor.
       | 
       | Is a pretty rough sentence for someone not familiar. I think Elm
       | does a pretty good job of exposing functional features without
       | falling into using these terms for them, and by simplifying it
       | all.
       | 
       | It does pay for that in terms of missing a lot of the more
       | powerful functional features in the name of keeping it simple,
       | but I do think it makes it a great entry-point to get the basics,
       | especially with how good the errors are, which is very valuable
       | when you are learning.
       | 
       | I know it's a controversial language on HN to some extent (I
       | certainly have my own issues with it _shakes fist at CSS custom
       | properties issue_ ), but I genuinely think it's a great inroad to
       | functional programming.
        
       | automatic6131 wrote:
       | The absolute state of github projects.
       | 
       | This project should be exactly 1 (one) file. The readme.md.
       | 
       | LICENSE - There is a license? Why? Someone might steal the text
       | for their own blog post? So what? The license won't stop them.
       | 
       | package.json - to install dozens of packages for... eslint. Just
       | install globally. It's just markdown and code examples. Yarn.lock
       | - ah yeah let's have this SINGLE, NON EXECUTABLE TEXT FILE be
       | opinionated on the javascript package manager I use. Good stuff
       | We have a .gitignore, just to hide the files eslint needs to
       | execute. wow. FUNDING folder - wow we have an ecosystem of
       | stating the funding methods?
       | 
       | This should have never been a github repo. This is a blog post.
       | It's a single, self contained post.
       | 
       | I hate this crap. We have 9 files just to help 1 exist. It's
       | aesthetically offensive.
        
         | wtetzner wrote:
         | Why do you care? Just link directly to the rendered markdown.
        
         | Otek wrote:
         | Wow, where should I start
         | 
         | > LICENSE - There is a license? Why? Someone might steal the
         | text for their own blog post? So what? The license won't stop
         | them.
         | 
         | But it's still good that author underlined that he don't want
         | it to be copied. What's wrong with that?
         | 
         | > package.json - to install dozens of packages for... eslint.
         | Just install globally.
         | 
         | Then other contributors won't know what version he used, what
         | config he had, he won't be able to easily recreate it on
         | different computer, etc...
         | 
         | > Yarn.lock - ah yeah let's have this SINGLE, NON EXECUTABLE
         | TEXT FILE be opinionated on the javascript package manager I
         | use.
         | 
         | That's author choice. Any good argument against it or you will
         | just criticize for the sake of it?
         | 
         | > This should have never been a github repo. This is a blog
         | post. It's a single, self contained post.
         | 
         | It's a blog post with 270 different revisions, 80 contributors
         | and a bunch of different languages. Show me how to easily do
         | that with a blog post.
         | 
         | > I hate this crap. We have 9 files just to help 1 exist. It's
         | aesthetically offensive
         | 
         | Why number of files is offensive to you? We have a couple tools
         | good at what they do to keep things consistent and organized.
         | Better to have these tools to keep standards than not.
        
         | jhrmnn wrote:
         | The document appears to have 80 contributors, that's hard to do
         | with a blog post. It could have been a wiki page. But then I'm
         | not sure if hosting a single repo on Github is harder than
         | hosting a wiki. And of course Github provides superior platform
         | for collaboration compared to a wiki.
        
         | seandoe wrote:
         | I think it's cool that it's a repo. Now other people can submit
         | pull requests and improve it. As for the files, bah whatever.
         | Go find a squirrel to bark at.
        
       | anewpersonality wrote:
       | The ROI on learning FP is absurdly low.
        
       | leetrout wrote:
       | Are there a lot of people writing JS with leading semicolons like
       | these examples?
        
       | pacomerh wrote:
       | I love these definitions and will bookmark. But there's a point
       | where you can't really explain FP concepts in plain English
       | right?.
        
       | hoosieree wrote:
       | They forgot "reason about" and "blazingly fast" which get thrown
       | around all the time without ever being defined.
        
       | aaaaaaaaaaab wrote:
       | Constant Functor            Object whose map doesn't transform
       | the contents. See Functor            Constant(1).map(n => n + 1)
       | 
       | Ummm... how is this constant?
        
         | debugnik wrote:
         | It ignores the mapping completely:
         | constant.map(...) == constant
         | 
         | Constant functors are only ever useful if you need to thread a
         | simple value through code that asks for an arbitrary functor.
         | I'd say that's rare even for abstract, type-level heavy code.
        
       | wodenokoto wrote:
       | Not a bad list of definitions but definitely not plain English.
       | 
       | It's quite technical even for experienced programmers.
        
       | [deleted]
        
       | nine_k wrote:
       | It looks like the Partial Application section is missing the most
       | widespread form of partial application, known as "creating an
       | instance".                 class A:         def foo(self, x):
       | # do something            a = A()       foo(1)  # self is already
       | "applied".
        
         | chongli wrote:
         | That's a very good point. People think of functional
         | programming languages and OOP languages as entirely separate
         | worlds that, like oil and water, do not mix. In reality they're
         | equivalent, they just have different ergonomics.
         | 
         | For example, lambdas can be translated to anonymous inner
         | classes.
        
       | labrador wrote:
       | When I was an assembly programmer, I knew C could help me
       | 
       | When I was a C programmer, I knew OOP could help me
       | 
       | When I was a JavaScript programmer, I knew TypeScript could help
       | me.
       | 
       | I don't know how functional programming can help me, but I'll
       | keep trying to find a reason because people say it can
        
         | jacquesm wrote:
         | You can get a lot of mileage out of functional programming as a
         | style without using a functional programming language, and you
         | can do it in (almost) any other language, the big one: avoid
         | side effects to functions as much as possible. That alone can
         | make all the difference between a maintainable, refactorable
         | and testable codebase compared to one that has side effects all
         | over the place. If that's all you get out of it that's profit.
        
           | labrador wrote:
           | That's always been good programming practice to me, not
           | functional per se. I learned the term 'spaghetti code' early
           | on and took it to mean not just gotos, but lots of flags,
           | especially globals.
        
         | aeonik wrote:
         | The biggest benefit I see is lack of side-effects. With a
         | functional program you can be sure that your can safely call
         | any function without having to worry about the current state of
         | your app.
         | 
         | A proper functional program can start to do very cool things
         | safely: like hot reloading of code. When I'm debugging a
         | Clojurescript app I can have a live running game, and update
         | the physics without even reloading the page. It's all live.
         | 
         | A proper functional program really looks like a series of
         | mappings from a collection of data sources to a collection of
         | data sinks.
         | 
         | The keyword for this is referential transparency:
         | https://www.braveclojure.com/functional-programming/
         | 
         | There are other benefits like composability, designing your
         | programs this way will give you access to algorithms that works
         | otherwise not work with your code. The simplest example is Map,
         | Filter, and Reduce. These functions are by their very nature
         | parallel because a compiler knows that there are no
         | intermediate steps, unlike a for loop.
        
           | jacquesm wrote:
           | Exactly.
        
           | labrador wrote:
           | I should probably add that I program mostly C# so I'm getting
           | Functional benefits like Map and Filter because Eric Meijer
           | added LINQ. He made it his life's work for a few years to
           | bring functional programming to the masses.
           | 
           | But I was minimizing state long before that because state
           | makes any program much harder to understand.
           | 
           | Confessions of a Used Programming Language Salesman: Getting
           | the Masses Hooked on Haskell http://citeseerx.ist.psu.edu/vie
           | wdoc/download?doi=10.1.1.72....
        
             | Rumudiez wrote:
             | C# might not be the best language to try FP in. F# is a
             | popular alternative that might feel more familiar than e.g.
             | Haskell. Since JS was one of my first languages, I learned
             | a lot just from using the library RamdaJS which helped
             | soften the learning curve for me
        
           | singularity2001 wrote:
           | Julia gives such beautiful examples for composabilty: Feed
           | 3km+-10m into an algorithm which was written with just
           | numbers in mind and units and confidence intervals often
           | propagate all the way through.
        
       | GnarfGnarf wrote:
       | Can someone clarify something for me? If you build a linked list
       | or a dynamically growing array in a Functional program, am I
       | correct in understanding that the array is never modified,
       | instead a copy is made and the new element is added to the copy
       | of the array?
        
         | olodus wrote:
         | The result should be that after the addition you should not
         | have affected the old array yes. The most basic way of
         | implementing this is what you described. However, there are a
         | number of different ways to optimize this. Since you know that
         | the elements are immutable, if you add the new element to the
         | start of the list you could just point it to the old elements
         | and you now have two lists which share the majority of their
         | elements. If you are interesting to learn about this more I
         | would recommend looking into how for example Clojure implement
         | their "persistent data structures". Most functional languages
         | have similar things so you could find it elsewhere as well if
         | you want.
        
         | pdpi wrote:
         | Immutable, fixed size arrays are pretty easy to handle in a
         | functional style, of course, but most functional languages only
         | discourage mutability while not outright forbidding it, so
         | you'll usually have access to mutable dynamically growing
         | arrays that work the exact same way as you expect them to.
         | 
         | Because functional languages _do_ discourage mutation, they
         | tend to fallback on an implementation of linked lists where the
         | lists are never modified (You can google for Persistent Data
         | Structures for more). Because the list never changes, you can
         | have two lists share a tail, by building on two different heads
         | atop that tail (like a git branch of sorts, minus the merging).
         | 
         | If you want to build a pure language, you can build immutable
         | dynamic-sizeable arrays with a copy-on-write setup. Growing the
         | array keeps building on top of the existing buffer, if you
         | outgrow it or need to actually mutate it, you make a copy.
         | 
         | If you want both purity and actual full-on mutability, e.g.
         | Haskell has Data.Array.MArray, which locks the array behind a
         | mutable context (like IO), so your pure code never sees any
         | mutation.
        
       | Dagonfly wrote:
       | Some helpful explanations in there!
       | 
       | Though I think the closure example doesn't actually show
       | capturing context. It's just a partial function application
       | unless you count the literal '5' as a local variable.
        
       | onlyfortoday2 wrote:
        
       | eddyschai wrote:
       | Obligatory "Hitler reacts to Functional Programming"
       | 
       | https://www.youtube.com/watch?v=ADqLBc1vFwI
        
       | synu wrote:
       | It would be cool if this also told you why you might want to do
       | the thing it's describing.
        
       | TrackerFF wrote:
       | While I appreciate FP using terminology from its math origins - I
       | do think it's a huge barrier for entry, and not really sure
       | languages that cling onto them, will see much real mainstream
       | success.
       | 
       | But then again, I don't think the language maintainers et. al.
       | are too concerned with widespread success. Just some
       | observations, but the majority of people I know that actively use
       | FP languages, are academics. I've encountered some companies that
       | have actively gone with a FP language for their main one - but
       | some have reverted, I guess due to the difficulty of hiring.
       | 
       | With that said - functional elements are becoming more common in
       | widespread languages, but not all the way.
        
         | dkarl wrote:
         | I think using math terminology is honest, in that it gives an
         | accurate expectation of how the ideas can be communicated and
         | learned. They are simple ideas that can be communicated in
         | their entirety in just a few symbols, but it takes time,
         | exposure, and practice to develop facility in their use and a
         | feeling of "understanding."
         | 
         | That's the math experience. I know people hate that and would
         | much rather it be a matter of reading some a nice explanation
         | and then "aha" but there's no such explanation yet and after
         | years of people trying to develop one there's no point in
         | expecting one right around the corner.
        
         | ebingdom wrote:
         | I agree about the math terminology, but I think it would be
         | more confusing if we created a completely different set of
         | vocabulary for the same concepts. So I don't really know what
         | to do: refer to something by its proper name, or create a new,
         | less precise name to make it sound less scary? Why do we find
         | certain identifiers scary in the first place?
        
         | ncmncm wrote:
         | A "functional language", like an "object-oriented language", is
         | an exercise in futility. But support for a functional approach
         | in a general language will often be useful.
        
       | ribit wrote:
       | Now can someone do the same for web dev? I just started getting
       | into it for a hobby project and the terminology is so incredibly
       | idiosyncratic.
        
       | ijidak wrote:
       | This is great. Finally understand monads a little better.
       | 
       | Definitely saving this for later.
        
         | ratww wrote:
         | Btw, that "chain" function is available natively in Javascript,
         | as "flatMap". Monads aren't as mysterious as we make them look.
        
         | jstx1 wrote:
         | Why do monads come up so often when people talk about FP? Is it
         | a meme or are they really an important and difficult to
         | understand concept?
        
           | pdpi wrote:
           | If you want a lazy-by-default language, you need to deal with
           | a problem -- laziness means you don't need to actually
           | evaluate the reads until you use `a` and `b`, and the print
           | uses `b` before `a`, so the two reads can be executed in
           | reverse order:                   a = read()         b =
           | read()         print("{b}, {a}")
           | 
           | One of Haskell's original goals was precisely to be lazy-by-
           | default, which necessitated coming up with a way to solve
           | this problem, and monads are the solution they came up with
           | that gave us reasonable ergonomics. From a practical point of
           | view, monads are just types that have reasonable
           | implementations for three simple functions: `pure`, `map`,
           | and `flatten`                   # lists as monads:
           | pure 1 = [1] # put a value "inside" the monad         map f,
           | [1, 2, 3] = [f(1), f(2), f(3)] # apply the function to the
           | "inside" of the monad         flatten [[1], [2, 3]] = [1,2,3]
           | # take two "layers" and squish them into one
           | # also, the simplest, but least useful, way to use functions
           | as monads:         pure 1 = (x -> 1) # putting a value inside
           | a function is just giving you the constant function
           | map g, f = (x -> g(f(x))) # map is just composition
           | flatten f = (x -> f(x)(x)) # you squish by returning a new
           | function that performs two nested calls
           | 
           | ("reasonable" here largely means "they follow the principle
           | of least surprise in a formal sense")
           | 
           | The trick is that, once you know what monads are, you can use
           | them in any language (with varying degrees of support), and
           | you can see instances of them everywhere, and it's an
           | incredibly useful abstraction. Many common patterns, (like
           | appending to a log, reading config, managing state, error
           | handling) can be understood as monads, and compose quite
           | well, so your program becomes one somewhat-complex data type,
           | a handful of somewhat-complex functions that build an
           | abstraction around that data type, and then lots of really
           | small, really simple functions that just touch that
           | abstraction. I have a .class parser written in Scala that
           | exemplifies this general structure, need to put it up
           | somewhere public.
        
           | ufo wrote:
           | I think one of the reasons for the meme is because there's so
           | many monad tutorials. When a Haskeller is introduced to
           | monads they'll run across all these monad tutorials with
           | abstruse analogies for what a monad is. Is a monad a burrito?
           | Or a space suit? Odds are that none of these analogies will
           | make much sense and the programmer will have to figure out on
           | their own, what is the deal with monads after all. At some
           | point they might have an epiphany; monads are the sort of
           | idea that is actually pretty neat when it "clicks". They will
           | feel compelled to write a monad tutorial, and thus history
           | repeats itself.
        
           | lopatin wrote:
           | They come up because people who don't understand them think
           | they are important and people who do understand them want
           | other people to know.
           | 
           | Also, speaking of memes:
           | https://www.youtube.com/watch?v=ADqLBc1vFwI
        
           | AtNightWeCode wrote:
           | I think it is because monads can be used for handling side
           | effects, even though side effects do not exist in FP. :)
        
           | imtringued wrote:
           | public static void main(String[] args)
           | 
           | Why does this come up so often when people talk about Java?
           | 
           | Because beginners are confronted with the IO Monad if they
           | want to write a Hello world program.
           | 
           | Monad is a typeclass that any datatype can implement. Monads
           | have a then or flatmap like function that takes a Monad and a
           | function that operates on the contents of the monad but also
           | returns another monad of the same type which is then combined
           | according to the implementation details of the specific monad
           | that implements the monad typeclass.
        
           | frogulis wrote:
           | Many important "effects" (e.g. non-determinism, IO,
           | asynchrony, environmental context, state... etc) are modelled
           | as monads in Haskell.
           | 
           | You _can_ write Haskell code without understanding what a
           | monad is, but composing and creating these things is going to
           | be a little painful without that understanding.
           | 
           | Additionally, it seems to be a harder concept to grasp than
           | e.g. functors or monoids.
           | 
           | I think this can be partly attributed to many Haskell
           | programmers first being introduced to monads that are less
           | than ideal for understanding the concept.
           | 
           | Shameful plug, I've written some thoughts on this here:
           | https://frogulis.net/writing/async-monad
        
             | tymscar wrote:
             | I think this was some amazing insight. I understand monads
             | and I can use/write them but I feel like the concept hasn't
             | FULLY clicked yet. While even now it hasn't, I feel like
             | your blogpost got me that step closer to it, so thank you!
        
           | lucasdicioccio wrote:
           | There is a myth that "monads" are magical insights of some
           | sort -- it's not.
           | 
           | Difficult to understand: likely yes because the myth is not
           | groundless. What "monads" capture is how to combine things
           | with a lot of ceremony: (0) the things that we want to
           | combine are sharing some structure/properies (1) we can
           | inspect the first thing before deciding what the second thing
           | is (2) we can inspect both before deciding what is the
           | resulting combination. What requires a lot of thought is
           | appreciating why "inspect, decide, combine" are unified in a
           | single concept.
           | 
           | Important: indeed, because in Haskell-like languages monads
           | are pervasive and even have syntactic primitives. It's also
           | extremely useful when manipulating concepts or approaching
           | libraries that implement some monadic behaviour (e.g.
           | promises in JS) because the "mental model" is rigorous. If
           | you tell someone a library is a monadic-DSL to express
           | business rules in a specific domain, you're giving them a
           | headstart.
           | 
           | Some final lament: there's a fraction of people who found
           | that disparaging (or over-hyping) the concept was a sure-fire
           | way to yield social gain. Thus, when learning the concept of
           | monads, one situational difficulty that we should not
           | understate is that one has to overcome the peer-pressure from
           | their circle of colleagues/friends. Forging one's
           | understanding and opinions takes more detachment than the
           | typical tech job provides.
        
           | xigoi wrote:
           | Haskell uses monads as an escape hatch for performing side
           | effects, so they come up often there.
        
             | endgame wrote:
             | Not as an "escape hatch" (that would be something more like
             | `unsafePerformIO :: IO a -> a`), but as a principled way to
             | compose (among other things) IO actions.
             | 
             | A Haskell program executes the IO action at `Main.main`,
             | which must have type `IO ()`.
             | 
             | `putStrLn :: String -> IO ()` is a pure function - if you
             | give it the same input, it always the same IO action as a
             | result.
        
               | ogogmad wrote:
               | Monads are (for better or worse) contagious. So when one
               | function calls a monad, then it needs to be included in
               | the monad as well. It makes introducing memoisation to a
               | file, randomisation, and memoisation not-to-a-file
               | (without using lazy evaluation to express it) difficult.
               | I don't know whether the alternatives (effect systems for
               | instance) help with this.
               | 
               | I personally don't use functional languages because I
               | find them too difficult given the needs and interests I
               | have. I think about computations sequentially most of the
               | time.
        
               | ratww wrote:
               | Monads themselves aren't really contagious, it's the
               | actions that would otherwise have side-effects that are,
               | and also the fact they have to be executed in sequence.
               | 
               | This is also true for other things in other paradigms,
               | such as async functions in javascript.
               | 
               | This is a good thing, however. In imperative programming,
               | you have invisible temporal coupling. In pure-FP you have
               | the same coupling, but it's exposed.
        
               | garethrowlands wrote:
               | While I broadly agree with you, I think the post you're
               | responding to has a point. You can't, in general, get a
               | value back out of a monad, so if you call a monadic
               | function, you may well have to return a monad. The
               | obvious example is IO: there's no (safe) way get the `a`
               | from `IO a`, so IO is kinda contagious.
               | 
               | Then again, there are lots of monads, such as `Maybe` and
               | `List`, where you _can_ get values out. These aren 't
               | contagious at all.
               | 
               | I agree with you that this is a good thing. Effects show
               | up in the type signature - and it's all about those
               | effects and managing them.
        
               | ratww wrote:
               | Yes, this is what I mean. IO is contagious for reasons
               | unrelated to it being a Monad.
        
               | endgame wrote:
               | I think that applicatives and monads feel more contagious
               | than they really are, because at first people tend to
               | write functions that consume values of type `f a` too
               | readily. This is because it takes some time to become
               | comfortable with `fmap` and friends, so the new Haskell
               | programmer often doesn't write as many pure functions.
        
               | fhars wrote:
               | But then monads _are_ a way to think about computations
               | sequentially. If I write highly sequential code in a
               | C-like language, in many cases most of the code is just
               | boilerplate made necessary by the absence of native
               | support for monads:                   int ret =
               | doStepOne();         if (ret == RESULT_OK) {
               | ret = doStepTwo();         }         if (ret ==
               | RESULT_OK) {             ret = doStepThree();         }
               | return ret;
               | 
               | would just be                   doStepOne() >>=
               | doStepTwo() >>= doStepThree()
               | 
               | in a language with support for monads.
        
           | alpaca128 wrote:
           | I'd say both.
           | 
           | For me the difficulty comes from the formal
           | explanations/definitions, those always manage to confuse me.
           | Result & Option types seem to have something to do with it so
           | I may already have some understanding of the concept. But
           | many explanations containing the word Monad also contain
           | various other abstract mathematical terms. Trying to explain
           | the concept to someone without mathematical background can be
           | tricky.
        
           | goto11 wrote:
           | They are used pervasively in Haskell, less so in other
           | functional languages.
           | 
           | In Haskell, you can't write a "Hello world" program without
           | using monads, so you cant really avoid learning about them.
           | 
           | IMHO monads are only really useful in Haskell because it has
           | specific built-in syntax sugar to support them. Without this
           | syntax sugar, they would be very cumbersome to use. So it's
           | not really the monad type per se which is interesting, it is
           | the code style which the syntax sugar enables.
        
             | IAmYourDensity wrote:
             | And the reason you can't write "Hello world" in Haskell
             | without using a monad is that functions in Haskell are
             | "pure", meaning they cannot have side effects like
             | outputting to the console.
             | 
             | Preventing side effects, including reading and writing
             | global state, helps prevent bugs and makes it easier to
             | understand and refactor Haskell code. Some would argue that
             | the extra layers of abstraction from category theory and
             | unpredictable order and number of lazy evaluations can
             | actually make it harder to understand and refactor Haskell
             | code.
             | 
             | Anyway, in order to perform I/O in Haskell, you evaluate
             | your pure functions as a sequence of actions that are
             | executed by the Haskell runtime. The construct that helps
             | you build the sequence of I/O actions and allows you to
             | bind their intermediate values to arguments to be used by
             | subsequent actions is called the 'IO' monad.
        
             | garethrowlands wrote:
             | While it's true that `IO` in Haskell has a `Monad`
             | instance, you don't really have to know that to do `IO` in
             | Haskell. Certainly you don't need to know `Monad` in the
             | abstract to use `IO` concretely.
             | 
             | I like Haskell's `do` notation, which is its syntax sugar
             | for monads, but it's really not _that_ bad without. For
             | example:                   do name <- getLine
             | putStrLn ("Hello " ++ name)
             | 
             | isn't really _that_ much nicer than:
             | getLine >>= \name-> putStrLn ("Hello " ++ name)
             | 
             | or even:                   getLine >>= \name->
             | putStrLn ("Hello " ++ name)
             | 
             | The main reason that monads are important in Haskell is
             | that programs that do IO simply are not functions in a
             | mathematical sense. If Haskell were limited to functions,
             | it wouldn't be able to do IO.
        
       | pseudosavant wrote:
       | I didn't really understand FP until I read Functional Light
       | JavaScript by getify/Kyle Simpson. It is so well written and
       | approachable by mere mortal coders. I'm not an FP wizard, but it
       | is the coding paradigm I mostly use now. I've even adapted some
       | aspects (e.g. composability) to the CSS I write using `var()`.
       | 
       | You can buy the book or read it on GitHub:
       | 
       | http://fljsbook.com/
       | 
       | https://github.com/getify/functional-light-js
        
       ___________________________________________________________________
       (page generated 2022-07-04 23:01 UTC)