top | item 31944352

Functional programming jargon in plain English

557 points| mgliwka | 3 years ago |github.com

184 comments

order

mjburgess|3 years ago

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, ...

stingraycharles|3 years ago

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.

HelloNurse|3 years ago

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

jmgimeno|3 years ago

Yes, but you're relying on the undefined concept of context. How do you define context?

irrational|3 years ago

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?

shikoba|3 years ago

> 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

yowlingcat|3 years ago

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!

mgaunard|3 years ago

Currying is just systematic partial function application for each argument.

init0|3 years ago

Send a PR to the repo!

naillo|3 years ago

"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.

eddyschai|3 years ago

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.

cratermoon|3 years ago

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".

pseudosavant|3 years ago

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

Latty|3 years ago

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.

TrackerFF|3 years ago

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|3 years ago

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|3 years ago

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|3 years ago

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.

goto11|3 years ago

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.

saithound|3 years ago

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.

bjarneh|3 years ago

> 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

marcosdumay|3 years ago

As a hint, any time you read "just" in mathematics, replace it with "exactly". That may make it clearer.

cinntaile|3 years ago

This is left as an exercise to the reader.

rbonvall|3 years ago

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.

labrador|3 years ago

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|3 years ago

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.

aeonik|3 years ago

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.

Akronymus|3 years ago

https://fsharpforfunandprofit.com/ This might provide a pathway to groking FP. As you mentioned in another comment to have c# experience, you should already have all the tools installed to get started in f# as well.

wodenokoto|3 years ago

Not a bad list of definitions but definitely not plain English.

It’s quite technical even for experienced programmers.

nine_k|3 years ago

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|3 years ago

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.

ncmncm|3 years ago

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|3 years ago

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.

jacquesm|3 years ago

"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...

ijidak|3 years ago

This is great. Finally understand monads a little better.

Definitely saving this for later.

ratww|3 years ago

Btw, that "chain" function is available natively in Javascript, as "flatMap". Monads aren't as mysterious as we make them look.

jstx1|3 years ago

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?

_benj|3 years ago

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.

crossroadsguy|3 years ago

I think the title should have `JS` in it, because for quite few people it just might not make sense. Besides the examples are such that the author seems to have been simultaneously competing in a obscured code brevity competition. Plus, language is definitely not "plain English" wrt jargons.

automatic6131|3 years ago

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.

Otek|3 years ago

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|3 years ago

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|3 years ago

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.

wtetzner|3 years ago

Why do you care? Just link directly to the rendered markdown.

GnarfGnarf|3 years ago

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?

pdpi|3 years ago

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.

olodus|3 years ago

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.

Jemm|3 years ago

As someone who learned coding in the days of Pascal and Fortran; can I just say: WTF and why!

synu|3 years ago

It would be cool if this also told you why you might want to do the thing it’s describing.

mgaunard|3 years ago

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|3 years ago

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.

k__|3 years ago

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.

ribit|3 years ago

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.

ww520|3 years ago

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.

leetrout|3 years ago

Are there a lot of people writing JS with leading semicolons like these examples?

Dagonfly|3 years ago

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.

aaaaaaaaaaab|3 years ago

  Constant Functor

  Object whose map doesn't transform the contents. See Functor

  Constant(1).map(n => n + 1)
Ummm… how is this constant?

debugnik|3 years ago

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.

epolanski|3 years ago

Every time I see these kind of posts I always think maths behind it is much easier than the "dumbed down" versions.

pacomerh|3 years ago

I love these definitions and will bookmark. But there's a point where you can't really explain FP concepts in plain English right?.

ris|3 years ago

And no explanation of fixed points.

jtdev|3 years ago

[deleted]

hoosieree|3 years ago

They forgot "reason about" and "blazingly fast" which get thrown around all the time without ever being defined.

singaporecode|3 years ago

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…

ratww|3 years ago

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.

rswail|3 years ago

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.

globalise83|3 years ago

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|3 years ago

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.

62951413|3 years ago

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.

krageon|3 years ago

> 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.

lordnacho|3 years ago

Doesn't every mainstream language these days allow you to pick what style you want according to the situation?