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

I think most people miss the philosophy of FP; even practitioners of FP. A good chunk of React and Javascript developers just don't get it. They harp on about immutability but really the statement is meaningless to them as it is essentially a buzzword.

I feel to really see the full picture you need to be able to do point free programming with a language that supports the point free style as a first class feature.

Functional programming is about function composition. If you haven't picked up on this notion, than you haven't fully understood FP.




Surely it's about functional application as much as it's about functional composition. E.g. currying, one of the signature idioms of functional programming, doesn't involve composition at all, but is more closely related to partial application.

I'm a bit skeptical of the premise that either composition or application is a high enough bar. Consider stack-based/concatenative languages such as Forth. Composition and application are foundational aspects of that language, but nobody really considers Forth to be functional. On the other hand, the concatenative language called Joy is considered functional -- by its authors at the very least -- but it also introduces purity to the mix.


Of course it's about function application. All of programming is about transforming data. This is obvious. Some procedure must be applied to some data to transform it. There is no programming paradigm or language that avoids this and therefore it is not worth discussing.

I bring up composition because this it is the most important differentiator between FP and all paradigms. I wrote about it another reply:

https://news.ycombinator.com/item?id=22292105


You ignore C++ template metaprogramming, that performs computation without applyit any functions :-)


Immutability may be a buzzword, but if you stick with immutable data, that does give you functional programming. The possible exception to this is that you could have certain kinds of real-world side effects in a language which only had immutable data.

FP used to mean just "no side effects". (Barbara Liskov mentions this old understanding of FP here: https://www.youtube.com/watch?v=qAKrMdUycb8). That is a desideratum for the even bigger buzz-phrases "referential transparency" and "equational reasoning", which are the goals of the FP research programme and have yet to really materialize.

As a counterpoint to your claim that understanding point-free style is a fundamental part of understanding functional programming, how about this 1998 paper by Andrew Appel, "SSA is Functional Programming" http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.34.3... which locates the essence of functional programming in the fact of immutable data (equivalent to imperative Single Static Assignment code).


You're not wrong. By simply making data immutable and just using function application you achieve something that's not too far off from function composition. I mostly advocate point free style for educational purposes and I believe in the end it doesn't matter too much whether you use one style or the other. I talk about the isomorphism briefly here: https://news.ycombinator.com/item?id=22299297

As to why I advocate the point free style for educational purposes and why I believe immutability is just buzz that hinders true understanding of why function composition is fundamental to FP I get into that here: https://news.ycombinator.com/item?id=22292105


First, I happen to strongly agree with your point-of-view/philosophical stance that composition is the essential nature of ‘functional programming’. However, and it is a big one, a vast majority (including the leading researchers and academic authorities in the area) are hopelessly and willingly tied to applicative programming as not only the default paradigm, but as they see it, the only paradigm.

I am quite aware Backus was talking about compositional programming in his Turing Award speech, and his work backs that position up, and as I stated, I think that is the proper ground level for functional programming, but most programmers do not agree.

The wide-spread and well understood meaning of functional programming is programming in an expression oriented way, with immutability of data and lack of side-effects being the tent pole rules, laziness/eagerness of evaluation becomes the pivot point between most languages, with the divergence between compositional and applicative languages being almost completely absent.

With all the conflation and mass propagation of the term functional, I have to agree with Conan Elliott and recommend a more rigorous approach to terminology, I don’t whether is adopt his usage of denotational in place of functional, but some clarity in the semantic space would be a good idea.

— Edited to fix autocorrected errors.


Really? Category theory (when applied to FP) is basically the theory of function composition. I would think this point of view is huge in academia due to the prevalence of CT among academia and FP.

>with the divergence between compositional and applicative languages being almost completely absent.

Most FP languages have facilities to do both anyway. And the isomorphisms between the two concepts are small in distance so it doesn't matter too much if you use applicative over compositional. So really when I say you should do "point-free" to see the big picture I'm advocating that more for educational purposes rather than practical (though I'm not opposed to practical).

That being said you and I are pretty much in agreement, I was just unaware of the whole academic thing.


With regard to the prevalent academic opinions, I was really referring to the nature of programming language syntax and semantics. I would say that Category Theory is essentially about function composition, but that then gets filtered down into so-called applicative languages. This designation is based heavily on the lambda calculus, in which application of terms to other terms is the prime mover for computation. Backus certainly wasn't talking about lambda calculus based semantics for FP, he was focused on strict compositional semantics with only non-named pipelined data being fed to compositional units. Most language researchers and writers just assume that any programming language uses function application as the basic unit of computation and so the language is naturally built in layers on this basic unit. So, 'point-free' programming in a language like Haskell is typically just considered good programming style, it is still used in a primarily applicative way. I'm not quite a no-application purist, but I really do see the algebraic beauty in avoiding named variables and skipping application as anything other than a definable operator to work on other higher-order functions.

Just for reference, if you want to see the divergence between applicative (which is basically every modern language in production or in research) and compositional look at some of Manfred von Thun's papers he wrote about the Joy Programming Language. Some people strongly disagree with his stance, but I find him easy to read in any event, see the link below. Also, in several places linked from [0], Thun discusses the Categorical Abstract Machine and has a few references which served as a nice jumping off point for more reading.

[1] http://joy-lang.org/papers-on-joy/joy-compared-with-other-fu...


Thanks. Very informative. I actually didn't know about Backus. I just assumed because of CT all academics who study FP view FP this way.

Do you have the source where Backus actually talks about the stuff you mentioned?


The canonical source for Backus is his Turing Award Lecture, which was turned into a paper, by which time he had renamed his system FFP (Formal Functional Programming). [0]. There was some longer term research into his FFP system, done by Williams and Wimmers (who gave a much loved talk titled ‘Sacrificing simplicity for convenience: Where do you draw the line?’ that I can not find a copy or transcript of to save my life in 1988) which evolved into The FL language also by Backus, with Williams and Wimmers[2]. There is a great succinct rundown of Backus’ work in this area and those who continued it in [3], it is a little lengthy so I didn’t want to just big block quote it.

Also, with regard to the CT thing, I totally get that. The predominance of CT-based concepts (no matter how far they are actually removed from the mathematical background of actual CT) are one of the defining features of modern functional programming, to the point people make jokes about needing to know CT to write ‘Hello World’ in Haskell. However, and I admit to having an unhealthy obsession with following PLT academia, it really is a little bit of a smoke screen. Nearly all ‘functional’ languages are based on the lambda calculus and various augmentations thereto, and so most of the CT applied in the area tends to be refinements and imports of various constructs into some potentially BiCartesian Closed Category (which is what the lambda calculus with the common functional programming additions of product and sum types and 1st class functions is as a category). But as I said before, the fundamental construct in the computational model is application via substitution. All of the advanced categorical constructs and tools still hold for compositional languages, but, as the theory goes, you gain an algebraic theory of manipulation of the actual programming language by virtue of the categorical properties of composition (and the inferred lack of hand-wringing over the semantics of substitution.

Sorry for the wall of text, this particular corner of CS and PLT is my favorite place, so any chance to talk about it I jump on.

—————————————————————- 0 - https://www.thocp.net/biographies/papers/backus_turingaward_... 2 - http://citeseerx.ist.psu.edu/viewdoc/citations;jsessionid=B9... 3 - http://joy-lang.org/papers-on-joy/joy-compared-with-other-fu...


> Edited to fix autocorrected errors

Missed one: Conal Elliot.

Poor Conal. He had to stop using the name Functional Reactivate Programming to Denotative Continuous Time Programming because the FRP name became a buzzword for a bunch of non-FRP systems


> function composition

Yes! But more broadly about composition in general.

Also datatype composition. Building DSLs that allow you to compose small constructs into larger ones preserving the same type so you can compose even further. Maybe even inhibiting some algebraic properties so you can reason about your compositions. About identity, reflexivity, associativity, transitivity etc.

So many real world problems can be tackled this way and getting this right can make you so extraordinarily productive!


>Yes! But more broadly about composition in general.

Functional programming in general is not about data composition. There is a difference between function composition and data composition in FP.

Function composition produces a new type given two separate types. In your example the type is the same.

In Haskell if you wanted to do data composition, you would need something like dependent types or some rudimentary form of it. If such a thing was invented, it may look something like this:

  a -> b -> (a * b) 
where a and b can be records or "structs" and (a + b) is the composed record. This type signature preserves the notion of parametric polymorphism in function composition which looks like this:

  (a -> b) -> (c -> a) -> (c -> b)
I'm no expert but as far as I know, in Haskell a new type must be defined manually when composing data but not when composing functions.

The tuple type actually shares an isomorphism with the concepts I am describing above. However it ascribes a sort of "order" on the types and feels more like a container of two types than it does a composition of types. I will illustrate below:

  a -> b -> (a,b) != a -> b -> (b,a)
  
  a -> b -> (a * b) == a -> b -> (b * a)
The ECS pattern among gaming focuses on the data problem you describe but largely suffers from the same issue as it is limited by the type system.


It's very easy to compose data in Haskell.

    data Expr = Const Int | Add Expr Expr | Mul Expr Expr
    myExpr = Mul (Add (Const 1 2)) 4
> There is a difference between function composition and data composition in FP.

The difference is rather blurry, because data constructors are very much like functions.

> Function composition produces a new type given two separate types.

Yes and no. The type might look different, but it's still a function! You can change the function domain to something else (like a DB query) to better see how this is actually type-preserving in a meaningful way:

    Query a b -> Query c a -> Query c b
Yes, the parameter types are different, but that's what makes this so powerful.


>Yes and no. The type might look different, but it's still a function!

The type is different. Functions are a class of types. The output of function composition is absolutely a different type but within the class of function types.

>It's very easy to compose data in Haskell.

I suggest you reread my post, I do not believe you fully understood it. You can compose data in ALL languages.

>Query a b -> Query c a -> Query c b

I mentioned the tuple type in my post which is essentially the same thing as what you're doing sans the constructor. In type theory these things are called "Product types."

Products are commutative, but in Haskell Data composition does not hold this property. See below:

  (a,b) != (b,a)
  Query a b != Query b a
while

  (a * b) == (b * a)
I am saying there is limited power in Data composition in Haskell, it is not as "complete" as function composition. It also brings nothing new to the table as the data compositional patterns are used outside of FP extensively.


> The type is different. Functions are a class of types. The output of function composition is absolutely a different type but within the class of function types.

I know how types and type constructors work, it's completely irrelevant in the context of what I was trying to say about composition in FP.

It seems to me you're probably talking about a very specific technical form of composition. I'm not.

To me a simple function like `vertically :: [Ui] -> Ui` is also about composition. The input and output types of the `vertically` function are not the same no, but informally we're still composing UIs into UIs. Which is exactly the level of detail I care for in this discussion.


Almost Every language has data composition if all you mean is "it's possible to wrap two things in a container" or "you can apply a function to two things and get a third thing".


Types can be composed in two ways. This is fundamental to type theory. It can be composed via a product or a sum.


> Functional programming is about function composition. If you haven't picked up on this notion, than you haven't fully understood FP.

Maybe that's exactly why the likes of Elixir feel so much less functional than some other FP langs. You don't usually compose functions, merely use function application (|>).


I think you've touched on an important point here, namely that functional programming is a feeling. We know it when we see it! But it's hard to get any two people -- even two domain experts -- to agree upon a common definition.

To me, functional programming is the feeling that you can successfully reason about a local fragment of code, because you know what the code (and its callers, and callees) can and cannot do with the data being passed around. It's functional in the mathematical sense -- i.e., the output is a pure function of the input, no matter how convoluted the definition -- and knowing this helps us to reason more clearly, mainly because we don't have to worry about unseen effects at a distance. So, functional programming is a feeling of confidence achieved by making data transformations as local and as pure as possible.


> functional programming is the feeling that you can successfully reason about a local fragment of code, because you know what the code (and its callers, and callees) can and cannot do with the data being passed around

That doesn't strike me as a very good definition. It's possible for an imperative language to be explicit about its data-flows.

The SPARK language does this. It's certainly not a functional language.

https://docs.adacore.com/spark2014-docs/html/ug/en/source/ho...


I'm not claiming that it's a good definition, and I won't try to defend it. It may also not be my definition of FP tomorrow. :) But my very point was that FP has a multitude of subjective definitions, at least in general conversation, so differences of opinion are always to be expected.

It's interesting that, while Ada is imperative, SPARK contract annotations aren't. I won't take up the challenge, but I think someone could argue that SPARK-minus-Ada may indeed be functional (although SPARK-minus-Ada is no longer a programming language).


'SPARK-minus-Ada' would be 'constraint programming' [0]. I agree with Wikipedia's taxonomy: constraint programming isn't functional programming. In functional programming, we can't just describe the problem, we still have to implement an algorithm. Not so with constraint programming. That's a bright line between the two.

I don't agree that functional programming is uniquely difficult to define. Again, I agree with Wikipedia, which offers a definition that seems fine: [Functional programming] treats computation as the evaluation of mathematical functions and avoids changing-state and mutable data. [1]

It's true that we can disagree on whether immutability, or function composition, should be considered the true crux of functional programming. This isn't unique to FP though. In the object-oriented world, some consider inheritance to be the heart of OOP, and some consider dynamic-dispatch to be what really counts. [3]

> SPARK-minus-Ada is no longer a programming language

I think I agree, but I think we're in a minority (we seem to disagree with Wikipedia here). If you're working at a level of abstraction so high that you no longer think about algorithms, you aren't really 'programming'.

'Constraint programming'... isn't. The 'programmer' isn't really programming, they're writing a formal problem-description.

Formal specification languages like B-Method [4] aren't considered programming languages, for the same reason.

[0] https://en.wikipedia.org/wiki/Constraint_programming

[1] https://en.wikipedia.org/wiki/Functional_programming

[3] https://news.ycombinator.com/item?id=21849366

[4] https://en.wikipedia.org/wiki/B-Method


Totally agree. I think that locality is what separates true functional programming from languages where some of functional programming features have been added on top. Immutability and types that track effects are means of achieving locality.


Try to not just stick to feelings. Feelings often indicate a lack of understanding. The ultimate goal is to coalesce that feeling into total understanding.

The definition of FP is fuzzy and it feels like a "feeling." However, as humans we can formally define the word with an exact definition that fits the "feeling." We've already done it with mathematics and it improved our understanding by a huge margin.


I agree in general that fuzziness isn't desirable. :) But the lack of a proper and widely accepted definition of FP is a perennial issue, and I don't see a resolution in sight. It's not a lack of clear understanding in my opinion, but rather a lack of consensus, and I'm not confident that FP will ever coalesce into a singular definition.

What I see in practice is that we have various tribes, using various FP languages, who each define FP in terms of the languages they use (e.g., an FP lang must have certain type-system features, or be non-strict, or etc.). To put it crudely, FP is the thing that we do in our language, and which we perceive others as not doing. I've used the term "tribe" intentionally, as I do think that tribal thinking has had a role to play in the muddying of the term.

Given this, I think it's reasonable to demote FP to the level of "feeling", at least in general conversation. Discussions within a certain language community, or in the context of a book or article, are a different matter of course since a formal, contextual definition can be given there.


>Given this, I think it's reasonable to demote FP to the level of "feeling", at least in general conversation. Discussions within a certain language community, or in the context of a book or article, are a different matter of course since a formal, contextual definition can be given there.

This was largely what people thought of mathematics before euclid formalized geometry. An exact definition exists for FP as it did for geometry and like geometry we will instantly recognize the definition of FP when someone finally decides to translate our intuition into formalization.


The |> operator isn't too far off from composition (.) in Haskell.

  b = (F.G.H)(y)
  (note F.G.H is a composition of 3 functions 
  into 1, it can be thought of as a single function that is 
  called with parameter y)
is not too far off from:

  b = y |> F |> G |> H
It's just the positioning of the "y" that changes.

The isomorphism between applicative and point free styles are so close that it basically doesn't matter which style to use. You can easily convert from one style to the other. I advocate the point free style more for educational purposes. To help you see that the composition of functions is fundamental to FP.


Do you have a rationale for drawing the line there? Why don't we go further and claim that (say) FP is also about laziness, if your language does not support first class laziness it's not functional. Or first class continuations, etc


Isn't programming about using abstraction to simplify complexity? You take two primitives and compose those primitives to form a simpler abstraction. This is the whole point of programming languages, otherwise we'd just use assembly as in the end it's all isomorphic anyway.

The question of how to Design things or how to abstract things in programming is thus in essence a discussion about different ways of composing things (aka different ways of abstracting things). It is the drive behind all the arguments behind different programming styles, different programming languages and different system designs.

The way you compose primitives in functional programming is through function composition. The debate between functional programming and procedural programming and OOP from a "design" perspective is thus the debate between which primitive composes better:

The function or the procedure or the object?

It's a question of Design and at the heart of it lies composition.

I think most people who love functional programming know on some level that the "design" of functional programs "feels" better. Most of them have never thought about "why" this is the case. They have never tried to answer the question of what is the true nature "design" from a programming language perspective. What is this vague thing we are optimizing for? We are constantly inventing new programming languages/patterns in attempt to answer the question and instead much of the time we move in a flat circle and come back to where we were before (see golang).

I believe FP moves the ball forward in terms of design. The thing is, most people can't see why. They rely on inexact feelings, and a lot of the times they even feel the opposite. I've heard people talk about FP is just a fad similar to design patterns and OOP. Without the ability to develop an exact concrete answer why one "design" is better than the other, we will always move in circles even when we discover a "design" that is actually better.

If you want an exact, concrete answer to the question of "design" the answer lies in the mechanics of composition.


I agree that the heart of the matter is abstraction and composition. I agree that function composition is an important part of FP. I agree that FP languages should allow point-free composition

However I think the claim "functional programming is about function composition", together with the claim that "other things commonly associated such as immutability are not defining features of functional programming", is a stronger claim that seems unsubstantiated. There are many design choices analogous to immutability vs mutability that people argue are defining features of or are not defining features of FP. A Lisper might argue that closures over first-class mutable data can be part of the FP paradigm, or even that an FP language must allow that, while a Haskeller might argue that no, this must be modelled on top of immutable data. I see merit in common arguments presented for both viewpoints. A Haskeller might argue that monadic composition and syntactic support for it is a defining feature of FP, because simulating it with only "plain" function composition is deficient in some way. A criticism of this might be that monad transformers don't compose well. They might argue functions that functions should not be strict by default, because non-strict functions compose better than functions which are not. There's a great Quora answer that talks about this (https://www.quora.com/After-Haskell-there-is-no-language-whi...) and I remember a blog post framing this more explicitly in terms of composition that I can't find right now. I'm just sketching arguments that I've heard/thought about, but all these arguments deal with composition, abstraction and functions.

I don't like the framing of "does a procedure or an object compose better" because not all design choices fall into one of those, in fact I think very few do in a useful way. Is multiple dynamic dispatch (e.g. Julia) a way to compose functions or objects?


>I don't like the framing of "does a procedure or an object compose better" because not all design choices fall into one of those

I never went into why FP is better. I only said I believe it is better and that composition lies at the heart of this differentiation. So you are offering an opinion on something that I haven't expanded upon yet.

Allow me to explain why I believe composition in FP is a "better design" than other paradigms. First let's get on the same page about the true nature of design. What is it? I talk about it here: https://news.ycombinator.com/item?id=21953290

Once we're on the same page on what is design in general you can read about why I believe FP is better in general. I posted on quora, a definition of "good design" in the context programming and program organization. Then I go into why FP under this definition is "better."

https://www.quora.com/Is-senior-full-stack-engineer-Ilya-Suz...

The answer is not straightforward and I get into the caveats in the comments on that quora post.

I believe the definitions for design that I am describing are universal and concretely illustrate what we all talk about when we talk about "design." If you have a different definition of design than the problem is just semantic in nature. At the very least I think we can agree that in terms of this definition of "good design" FP is the better than OOP and imperative.


You're still not defining what a "paradigm" is, which is my main objection. You define "FP" to be (what I claim is) a way that's too narrow. Your splitting the design space into different paradigms is (I claim) not substantiated. There is a large number of (what I claim are) different design choices such as immutability, first-class functions, monads, dynamic dispatch, etc. You're coming along and saying "some of these features are FP, some are OOP, others are procedural" without any reason why you divide them up this way.


Please carefully read what I posted. The links specifically. The topic is incredibly deep but my opinion on the topic is concrete and clear meaning that I believe if you read and completely understand what I'm talking about and still completely disagree with me, then our disagreement will just be semantic in nature which is just a disagreement on how we defined a word or what to call something.

If you follow the links, read and completely understand what I'm writing you will see I covered everything. Right now it appears you didn't read it.

In the links I provided, I define "design," and I operate within the bounds of that definition so you are clear about what I'm talking about. Please read.


> If you follow the links, read and completely understand what I'm writing you will see I covered everything. Right now it appears you didn't read it.

Which one of your links define the terms "FP" and "OOP"?


The second link. It's not strictly defined. You can piece together the definition from your intuition as a programmer and english speaker and also by what I write. If you have trouble doing this, let me know I can clarify.


My whole point - the one I've been trying to make in every comment in this thread - is that if you want to talk about "FP" as a whole (or "OOP" as a whole), you have to explicitly define it. Relying on intuition or culture is not enough.

Like, I use what I think of as FP features much more than I do what I think of as OOP features. In languages commonly thought of as multi-paradigm, say python, I have lots of higher-order functions, and lots of functions which are just compositions of others (I don't write point-free style though). I try hard to avoid implementation inheritance ("OOP inheritance") if possible. I know people who do the exact opposite thing in python.

But if I write down the definition of "FP" for me and you write down your definition, I 99% guarantee you they'll be different in a substantive way.

So I agree with many of the points you make in the links about how composition works in (what you think of as) FP vs OOP. But I view that as claims about individual design patterns or language features (and very big, fundamental design patterns / language features), not as things called "FP" and "OOP".


>My whole point - the one I've been trying to make in every comment in this thread - is that if you want to talk about "FP" as a whole (or "OOP" as a whole), you have to explicitly define it. Relying on intuition or culture is not enough.

I am aware this is your point. I understand your point. I don't know about you, but I find a conversation of your definition of a term vs. my definition of a term to be uninteresting. Arguing about semantics doesn't matter in my opinion.

>You define "FP" to be (what I claim is) a way that's too narrow. Your splitting the design space into different paradigms is (I claim) not substantiated.

>So I agree with many of the points you make in the links about how composition works in (what you think of as) FP vs OOP. But I view that as claims about individual design patterns or language features (and very big, fundamental design patterns / language features), not as things called "FP" and "OOP".

Your own statements show that you have already derived from my writing what you think I define as FP and OOP. You also implied something about what you believe I defined as "design" saying that I splitted it into "spaces" of different paradigms.

So why is there a need for me to explicitly define a definition for you when you already derived it from my writing? Is this your whole point? That your definition of OOP, FP and design is different from my definition but you understand what I'm talking about? Or is there another point you're trying to make?

Just to refocus: The topic of our thread is basically the rationale behind why I draw the line at function composition as the main point of FP. Given my definitions of OOP, FP and Design, do you understand why I have this rationale? And if you understand my rationale do you agree with it or disagree?


> Is this your whole point? That your definition of OOP, FP and design is different from my definition but you understand what I'm talking about? Or is there another point you're trying to make?

Let C1 be the following claim: "function composition is better behaved than object composition and procedure composition".

Let C2 be the following claim: "the most important part of FP is function composition".

I'm saying that you've provided arguments for C1 (that I mostly agree with). So let's say that I agree with C1. However, you haven't shown why C1 => C2, and I disagree with C2.

So to answer your question, I understand your rationale for C1 (and I agree with it), but I don't understand your rationale for C2, or for why C1 => C2.


>Let C1 be the following claim: "function composition is better behaved than object composition and procedure composition".

>Let C2 be the following claim: "the most important part of FP is function composition".

C9 = functional programming is better designed than OOP and procedural programming.

  I claim C1 to be true (you agree.)
  I claim C2 to be true.
  I claim C9 to be true.
  I do not claim C1 => C2

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reasoning for C2:

C3 = The primary task of High level programming languages is to simplify assembly instructions.

C4 = The simplification of assembly instructions is done through Composition.

C5 = Different High level programming languages/paradigms simplify assembly primitives in different ways.

C6 = High level programming languages/paradigms are, in essence just different ways of composing assembly primitives.

(C3, C4, C5) => C6

C7 = If programming languages are all just different ways of composing assembly primitives than how they compose assembly primitives is the most important part of the language and the main differentiator between one high level language and another high level language.

C8 = function composition is the primary form of composition for functional programming.

(C6, C7, C8) => C2

  ---------------------------------------
In short:

- High level programming languages/paradigms are, in essence just different ways of composing assembly primitives.

- If programming languages are all just different ways of composing assembly primitives than how they compose assembly primitives is the most important part of the language and the main differentiator between one high level language and another high level language.

- function composition is the primary form of composition for functional programming.

Therefore: the most important part of FP is function composition.

  -------------------------------------------

  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Reasoning for C9:

C8 = "A Design for a programming language" is just another phrase for "a method of composition for a programming language".

(C1, C8) => C9

  -----------------------------------------------
In short:

- function composition is better behaved than object composition and procedure composition

- "A Design for a programming language" is just another word for "a method of composition for a programming language"

Therefore: functional programming is better designed than OOP and procedural programming.

  ------------------------------------------------

I like this format, thanks for introducing it. I think it allows us to clearly see which axioms we disagree with and need to think about.


I guess the claim I disagree with is C8:

C8 = function composition is the primary form of composition for functional programming.

Most people consider Haskell to be a language that heavily encourages a "functional programming" style. If you take a look at idiomatic Haskell code, yes, you see a lot of function composition. But I think you also see a lot of composition that are distinct from "simple" function composition:

- Parametric polymorphism

- 'Monadic' composition (i.e. `>=>`)

- Applying higher-order functions


- Parametric Polymorphism is a way to define types or functions that are generic over other types. There is no composition going on here. So I disagree with you here.

- You bring up a good point about monadic composition and other forms of more advanced function composition. Although I don't explicitly mention these types of compositions my words encompass these forms of compositions as well. Additionally, technically the >=> is still "function composition" and "point free programming" as the operands and resulting composition are all still functions getting composed.

- Applying higher order functions? Do you mean function factories that take a function and return a new function?

So like C = A(B) where A, B, C are all functions and C is the "composition" of A and B?

The above shares an isomorphism with dependency injection. If A B and C were objects the syntax is exactly the same.

So I mention this in my second link as one of the caveats of OOP. This type of composition is equivalent to dependency injection or object composition. "A" cannot exist on it's own without "B." This is a bad form of composition. as "A" is dependent on "B".

If you do too much of this in your programs, then, like doing an excessive amount of dependency injection or object composition in OOP, your program will lose flexibility as it becomes a network of dependent primitives. Qualitatively, it also makes your code look like a giant mess if you do this everywhere.

That is why the above form of composition is not primary. If used at all it is only used sparingly and usually only on well known higher order functions like map, reduce or compose.

Caveat: It does get blurry here as the composition operator is in itself a function that takes in functions and produces a new function. This is where the isomorphisms between OOP, FP and procedural programming I talk about in the comments on that Quora post begins to meld the paradigms together.


You will note that you and many other FP programmers have gotten away with FP programming without doing a single line of actual function composition yet still yielding much of the same design benefits from the point free style.

This happens because the isomorphism between applicative and composition is really really close. I advocate the point free style for educational purposes, but for practical purposes either style is fine.

I get into the isomorphism briefly here: https://news.ycombinator.com/item?id=22299297

Where |> is the application operator. x |> f = f(x)


> Functional programming is about function composition

It sounds unnecessarily abstract. Isn't functional programming simply avoiding side effects? It forces you to use immutable datatype and write "pure" functions.


I believe that function composition is the heart of the matter. Side effects and immutability are just the consequences of trying to create a primitive that can be used under function composition.

In another post I illustrate exactly why I believe that it IS NOT necessarily abstract and in fact fundamental to FP: https://news.ycombinator.com/item?id=22292105


> Side effects and immutability are just the consequences of trying to create a primitive that can be used under function composition

I think I see what you mean, but it sounds like you see function composition as the end, where I see it as a mean. To me, being side-effect free is the end because it helps me doing local reasoning which ultimately makes programs easier to reason about. That being said, I understand it may be easier to characterize formally FP using function composition.




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

Search: