Leaving aside the category stuff for a moment, I think the first couple of paragraphs of this article make an excellent point.
> Functional programming is all the rage these days, but in this post I want to emphasize that functional programming is a subset of a more important overarching programming paradigm: compositional programming.
Indeed. So there is another article just begging to be written: "Introduction to Compositional Programming". I've seen any number of articles that say something like, "I especially like these because they are composable." But I've seen very little on figuring out how to solve problems by using composable components, or so that the solution itself is composable.
Another thought: we really should be giving more thought to composition when designing programming-language syntax and features. Haskell excels at writing composable components; it also has nice syntax for composing them. Both are much less natural in "C". Various replacements for "C" are being proposed; is thought being given to composability in them? Similarly, the popularity of Python's generators is largely because they allow for the easy design of composable components. Etc.
The point of this article is that you don't want to leave the category stuff aside. A category is essentially a well-defined and systematic way to reason about--and program with--composition. An introduction to programming with categories would, by its very nature, have to be an introduction to programming compositionally.
Moreover, I think a introduction using terms and ideas from category theory would be more useful, more thorough and more enlightening than an introduction to "compositional programming" without any math. It provides a nice structure and enables you to consider composition more abstractly, which lets you use compositional programming in more places.
> Moreover, I think a introduction using terms and ideas from category theory would be more useful, more thorough and more enlightening than an introduction to "compositional programming" without any math.
Yeah, this article left me wanting to know more about category theory. But that in itself is valuable. I googled and found a couple introductory papers [1,2], some slides introducing category theory for software engineers [3] (with a NSFW diagram on page 8), and an introduction to category theory as it applies to Haskell [4].
(1) There is still a software-design aspect to all this that has been neglected. For example, one can find all kinds of material on how to design OO software (e.g., the GoF book and its offspring). Find me something about how to design software using composable components. There isn't much out there.
(2) "Software engineers need category theory" is a statement that is almost too vague to be discussed. Certainly, a traditional presentation of category theory is largely useless to these people. What exactly is useful, and how should it be presented? People are starting to answer these questions, but only starting. Note, for example, that, in the brief intro to categories in the linked article, the fact that the categories allow for multiple identities (one for each object) is glossed over. It this a good idea? I don't know.
Composability in Haskell arises from abstraction made possible by a rich type system and simple semantics. IMHO and from my experience with dynamic languages, any syntactic solution to Composability will be a dead end, i.e. will not beget any other useful abstractions.
All true, but let's not forget that there is a nuts-and-bolts aspect to it, as well. The fact that we can write the wonderfully clear & concise
f = f1 . f2 . f3
in Haskell arises from the things you mentioned and also from the language syntax. In a language that is only slightly different, we might need to write something like
f = compose(compose(f1, f2), f3)
Indeed, despite Lisp's vaunted expressiveness, in many flavors of Lisp you'd have to write something about as complicated.
Certainly syntax is very important; but I would suggest my point still stands even if you allow all of haskell's syntactic bits (in this case the ability to define infix functions of non-word characters).
And I think haskell's type system actually comes into play in your second code block example: languages where function arity is dynamic or untyped will never be able to make use of that simple infix syntax rule in your first code block.
Indeed, despite Lisp's vaunted expressiveness, in many flavors of Lisp you'd have to write something about as complicated.
Common Lisp lets you redefine syntax to support equally easy function composition. You can even get rid of the parentheses syntax altogether and switch to Haskell syntax. People don't do it, though, because Common Lisp is not a functional programming language, and that also would be against Lisp nature.
I don't know if Clojure has reader macros that are as expressive as Common Lisp ones (I'd be happy to learn the answer from some Clojure hacker). Other Lisps are either very old or domain specific.
Clojure has a function (comp ...) that composes an arbitrary number of functions, and the macros -> and ->> that sort of pipe a value through a list of expressions. (Still new to clojure myself)
> Functional programming is all the rage these days, but in this post I want to emphasize that functional programming is a subset of a more important overarching programming paradigm: compositional programming.
Indeed. So there is another article just begging to be written: "Introduction to Compositional Programming". I've seen any number of articles that say something like, "I especially like these because they are composable." But I've seen very little on figuring out how to solve problems by using composable components, or so that the solution itself is composable.
Another thought: we really should be giving more thought to composition when designing programming-language syntax and features. Haskell excels at writing composable components; it also has nice syntax for composing them. Both are much less natural in "C". Various replacements for "C" are being proposed; is thought being given to composability in them? Similarly, the popularity of Python's generators is largely because they allow for the easy design of composable components. Etc.