But that is not the only reason. Haskell does much more aggressive optimisations than Java (and Scala, OCaml, F#). A large part of Haskell's space-usage reasoning issues come from the combination of lazy evaluation and these aggressive optimisations. Java and Scala code can contain plenty of deferred evaluation too, for example iterators, but the compilers simply don't do (and cannot do) such aggressive optimisations. Of course, this also means that much pure functional Scala/Java code can be poorly performing.
> There's at least a dozen languages you could have chosen, and that others have chosen for any given use case. within some bounds, it makes very little difference.
It's about quality of life and picking the right tool for the job. There are some problems I can solve in Haskell, that I simply could not solve in Java, it would be too hard and too much work. Java is a simple language and therefore it's much easier to reason about the performance and space usage. There are thus many problems where Java would be a better fit.
Perhaps when Java gets record types, sealed classes, pattern matching and other features. But right now, Domain Modelling in Java (and C++) is really painful compared to a higher-level language like Haskell.
This highlights the risk of building upon and investing in a closed-source and proprietary platform (Flash). Once Adobe discontinued it, it was inevitable that browsers would eventually stop supporting it.
Yes, I'm claiming the restriction will be too much for many people, assuming we are trying to create a new language here. However, expressing a solution as a catamorphism is a good thing to do and helps reasoning. It's a form of structured programming (recursion is the "goto" of functional programming!).
> Ah ha, but you see, you can perform transformations on tagless-final terms that are not strict catamorphisms ... so matching two levels deep is possible.
No this is not correct. Oleg provides a solution to double negation by creating a catamorphism that folds to a function. It's still a catamorphism. And folding to a function is not something the average Java programmer is likely to understand easily.
By "compositional datatypes", I mean being able to define datatypes and functions on them in a modular fashion. I gave a very simple example with enums. For a real world use case, imagine a compiler pipeline, where we have an AST that we are desugaring over multiple steps. Ideally we want a succession of ASTs that remove the form being eliminated, so the AST type can guarantee it's eliminated. This is very easy with structural variants, there's no need to actually define and name each separate AST, which differs only slightly.
Or imagine we are typing a SQL join that is a merge of two existing record types. Such "compositional data types" can be achieved with elaborate encodings and type-level computations in a language like Haskell (see e.g. Data types `a la carte), but it's difficult and somewhat ugly. There is an opportunity here for improvement.
Are they perhaps scared of patents? The whole UI tries hard to be not like Windows or Mac OS, for IMHO little user benefit.
I have tried to use Gnome in the past, seeking an easier life, but the multiscreen support was just not good enough. I use i3 instead.
Not really a valid comparison. If you buy a pair of high-end Sennhiesers, they'll last many many years. I still use my HD580 from the 90s. They also sell all the necessary spare parts and are easy to repair (mine have had new cables and pads). An Apple product be will be e-waste in less than 10 years, the glued-in battery will start failing in less than 5.
If the artist makes and sells the CD themselves, it could be close to 100%. This old article from 2013, says a typical figure for major labels is 13%:
https://www.bbc.co.uk/news/magazine-23840744
What exactly do you mean by "build quality"? Do you just mean built from glass and aluminium? (hardly obvious choices for a laptop). IMHO, Apple can hardly claim to be leading in "build quality", what with glued-in batteries, un-repairable designs and keyboard reliability issues that have been ongoing for years.
It was certainly well marketed. But in reality, Spring is also too complex. It has far too much dynamic dispatch, byte-code weaving magic and runtime failure. This is now causing them problems with GraalVM and fast startup times needed for cloud.
Oops, yes I mean't JSP not JSF. I almost want to learn more about JSF, out of morbid curiosity. I'm guessing one can't bookmark any pages and the back button is broken?
In some future decade, when Banks start trying to migrate their "Enterprise Java" systems, anyone that can make sense of that bizarre and rather absurd model of computation is going to get well compensated.
My jaw dropped the first time I learned that JSF was translated (not sure compiled is the right word) into Servlets full of print statements. And of course no JSF-based application has ever managed to produce valid well-formed HTML ever since.
If one wants to learn what the Monad abstraction is, then one by definition will have to learn some category theory! I don't think there is any need to understand what a monad is in order to use any practical programming language. My point was that the burrito analogy does more harm than good (as predicted by Dijkstra).
I cannot imagine a mathematics lecturer telling his students "a monad is like a burrito". Sometimes I think the analogies can actually hurt our understanding of something very abstract or novel, as is the case with the bad burrito analogy.
I think what you are asking for are first-class parameterised modules, which is certainly a feature that OOP has that many FP languages don't. It does exist in some FP languages though, for example OCaml and the 1ML paper and language.
Most FP languages are already incredibly good for the amount of funding and development they have received. They could be so much better if industry / US big-tech actually started investing in them or the ideas behind them.
The reasoning behind "closures", is that one can capture some context such as the example you describe. If we think of an object as simply a record of functions, then we can close over some shared context during the construction of such records, if we have a language with records and closures.
"Dependency injection" frameworks look to me like a hack. In a more expressive language, such as F#, one could probably describe what needs to be done symbolically, and then write interpreters that implement the different behaviours required.
> What you see in K8S is the exception rather than the norm in Go - but is the norm in other languages.
I suggest that is because not many large applications have yet been built in Go and it is still relatively young. If Go was used more sparingly as a "domain-specific language for concurrent network services", then I might be inclined to agree with you, but it seems to be marketed and promoted as a general purpose language.
> Yeah it's hard to write weirdly complicated code in Go
Just because Go lacks many forms of abstraction, doesn't mean complex code will not be created with it. Quite the opposite. It's lack of expressiveness will encourage "frameworks", elaborate encodings, code generation and various productivity aids. Look at what the lack of generics has done to the Kubernetes code base:
"The core team replaced a compile-time language feature that was missing (Generics) with their home-built runtime system"