The words catamorphism, semigroup and monoid barely make sense to most programmers.
The words catamorphism, semigroup and monoid barely make sense to most programmers.
Another angle to view it is what if I told you that you could eliminate an entire class of errors by employing this abstraction? Learn Option once and then never have to deal with NPE's. What about errors due to recursion? Would it be appealing to avoid those errors forever? Concurrency, state, error handling, all things that have appealing abstractions.
If the idea of mathematical connections to seemingly unrelated things appeals to you, or you are tired of dealing with the same bugs in different forms then these abstractions seem very appealing. The problem is that it's a technical solution to a human problem. That doesn't inherently make it bad, but it does imply a different set of tradeoffs.
I think it's not too far from practicality to describe the solution in OP as along the lines of "solving fizzbuzz by combining infinite streams". It's a quirky/cute solution.
I think there's a jump from "knowing these functions / structures can be useful" and "let's use terms like 'semigroup resonance' and 'catamorphism'".
Names like StateT and Reader can surely be improved but the names taken directly from mathematics are already the best we can do imo.
However, I completely agree that the word "functor" is useful for exactly the reason you imply. It's a kind of special container. It doesn't work exactly the way you imagine containers should work initially. So I guess it's 6 of 1 half a dozen of the other. I just wanted to speak out because I know there are others like me that find reasoning about functors as if they are containers very useful.
Over the last few years I have absorbed a lot of these terms via professional Haskell development and have come to the conclusion that it is quite unfortunate that most of us tend to shy away from this unfamiliar vocabulary. It turns out these are very precise (mathematical) terms which describe common things we see every day in programming.
Addition, multiplication, and string concatenation are all monoids (described as: an associative binary operation with an id element). This might not seem useful to know on the surface, however, once you discover that you can write generic functions over any monoid you can start eliminating large classes of errors that tend to turn up in software development due to the DRY principle.
> An extreme attempt to simplify?
It turns out that the more generic you make something, the harder it is to do the wrong operations on it.
id :: a -> a
If 'a' is a generic type value for all possible types, is it possible to return anything other than the initial value passed in?A family man might read a book about FP patterns to solve common issues, agile, QS+testing, concurrency, etc (actually seen tgese read by 50yo collegues) - but not a single one has a category theory book on their table.
Its a question of time invested vs benefits to current occupation.
FP terminology is the domain of the young and the driven, who also are of academic age. (Probably winy find any junior-high kids dabbling with semigroups anytime soon)
The gist is - by having many simple-but-powerful tools along with many simple-but-powerful ways of composing such tools, it makes programming real problems way less intense. The cost of course is the learning curve. So I think of it has shifting variable cost of development to fixed costs upfront.
The end result in my experience is being able to handle more complexity than otherwise (good for side-projects.) Or to handle the same complexity with less time and effort (good for FT engineering...to make room for said side-projects.)
(Those terms actually have very general and simple definitions that I've seen interns learn in one teaching session. But they are infinitely useful problem solving techniques that I use all the time.)
The linguistics issue here is real and should be addressed or we will end up into two camps, and one will eventually give way to the other.
And math-hardcorers be warned, Life prefers the simple.
My take is you should know all these, and choose the appropriate level for what you're doing. You don't need to crank it up to 13 everywhere just because it's there. I spend most of my time (web apis, business logic) around level 7. If you dial the abstraction level too far up, not only does the code seem confusing, but it's also easy to paint yourself into an abstraction corner, where a new requirement comes in that breaks the abstraction, so you end up either tearing it down and rebuilding it completely, or building up a terrible "spaghetti abstraction" which is the worst kind of spaghetti. It's a bit ironic to think that abstractions are exactly what's supposed to prevent you from being painted into a corner, but it can happen easily. (https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstracti... is a good reference).
When writing things like compilers, the abstraction level can comfortably go higher. In fact it should. It makes challenging logic far easier to reason about and more consistent to specify and implement when you can think about it mathematically. Other things like rules engines and such can live comfortably in between the two. Conversely when writing timing-critical device code then the appropriate level of abstraction is much lower. A good reference for this style is the k8s PV code. Note the comments starting on line 55 (tldr: DO NOT SIMPLIFY THIS CODE) https://github.com/kubernetes/kubernetes/blob/ec2e767e593953...
So as developers we have to determine what the appropriate level of abstraction should be for our use cases. In fact I'd offer that's one of the most important parts of software design. But it's important to know all of them so we can choose accordingly.
The haskell model is much more intuitive and productive for me than the weird oo-esque models of “usual” languages like python, c++, and java.
I’m familiar with the theory behind popular styles like OO and have used them professionally but ultimately I find Haskells incredibly simple and constrained type system (closed data types, no subtyping, essentially total inference, purity, etc) easier to think in than the Wild West of python or java, say, since there are fewer modeling choices to make.