I would add that the elitist signaling that is rampant in functional programming in general and the Haskell community in particular is also not helpful.
I would add that the elitist signaling that is rampant in functional programming in general and the Haskell community in particular is also not helpful.
If I tell someone “I’m not smart enough to use php”, I’m admitting a weakness. I genuinely don’t have the mental capacity to keep details straight when using it. If I tried to use php for at a job, I’d move at such low velocity that I’d get PIP’d.
Or like saying “I can’t write code without automated tests.” there are genuinely people who, if they try to write code without tests get stuck for hours and don’t know how to move forward.
I’d think someone this is the same sentiment. I’m willing to believe that the Haskell community is elitist in other ways. But how is “I’m not smart enough to X.” An expression of that?
Imagine a programmer who, when she studies Haskell, discovers that the way it resembles category theory provides really effective mental affordances to her memory. She feels that Haskell's formalism makes it easier for her to have a clear mental model. When she writes and reads Haskell, she can predict what that code does to data and her predictions are largely correct. She feels confident in her understanding. This means that if she has a business goal she needs to fulfil, she's confident she can estimate that task, communicate about with stakeholders its complexity. and execute it.
Imagine that this programmer, when she starts to study PHP, does not find similar affordances. She finds it difficult to build a conceptual structure of it in her head. She finds that she forgets things or overlooks things when she tries to write PHP. If she tries to predict how a piece of code she writes in it behaves, she frequently is wrong. She feels very nervous about it. Consequently, when asked to plan adding a feature to a PHP task, she doesn't feel she's got a good enough grasp of her tools to answer. She worries about the risk to the business of her blowing past estimates and leaving making errors in production.
She tells someone "I don't think I'm smart enough to write PHP".
1) Is this statement a lie? 2) Is this statement elitist? 3) Is she a person who could exist?
What if her positive feelings about Haskell lead her to evangelise it in a way that ignores the fact that another person's brain might work in a different way to hers. She claims to this other person that Haskell is easy.
4) Does that statement make her elitist?
-----
My answers: No, No, Yes, Kinda yea.
You know what, use whatever makes you happy, while we continue to avoid success at all cost.
Functional programming is just one of the paradigms, and useful in it's own domain. Its not a end all solution to everything.
What are you basing this on?
It's a fresh, and pragmatic too, take on how to do pure functional programming, but without advanced concepts (like higher-kinded types).
could be (and maybe even has been) ported over to other languages besides Scala
Ah, so Common Lisp then?
And look, defining a problem functionally works great on 10% of the cases, but it complicates some 40% of other cases (very imprecise numbers).
The world is not functional, as it turns out. And a lot of those cases where you can write functionally don't gain much from a performance or correctness perspective compared to the procedural version
What does this even mean? If the world is not functional, then what is it? Is the world procedural? And what world are we talking about? Our planet, physically? Are you then discounting the worlds of mathematics and logic? You don’t gain performance? What performance? Program execution speed? Development pace and time to market?
Compared to the procedural version? Is your view that procedural programming is inherently better — for any definition of the word — regardless of context? Would SQL queries be easier to write if we told the query planner what to do? Is the entire field of logic programming — and by extension expert systems and AI — just a big waste of time?
So many vague aphorisms which do nothing to further the debate. And Haskellers are the ones getting called “elitist”!
> What does this even mean? If the world is not functional, then what is it?
The world is full of special cases, of corner cases, of exceptions, of holes, of particular conditions, of differences for first or last element, and other irregularities; it is also full of sequential events. Applying a function to a starting set, to produce a resulting set or value is very lean with clean nice mathematical objects and relations, but not with many real-world problems.
> And Haskellers are the ones getting called “elitist”!
Well, one may say that answering with questions could fit the bill...
True
> Applying a function to a starting set, to produce a resulting set or value is very lean with clean nice mathematical objects and relations
True
> but not with many real-world problems.
Debatable, but in any case a non-sequitur. Are you sure you're talking about functional languages as they're used in reality?
I once wrote a translator between an absurdly messy XML schema called FpML (Financial products Markup Language) and a heterogeneous collection of custom data types with all sorts of "special cases, corner cases, exceptions, holes, etc.". I wrote it in Haskell. It was a perfect fit.
Yes. All of which are modelled in Haskell in a pretty straightforward manner. I’d argue Haskell models adversity like this better than most languages.
> but not with many real-world problems.
Haskell is a general purpose language. People use it to solve real world problems every day. I do. My colleagues do. A huge amount of people do.
> Well, one may say that answering with questions could fit the bill...
I see. So trying to define the terms to enable constructive discourse is elitist. Got it.
If you want me to be more concrete and assertive, fine. No problem. Here we go.
You are wrong.
SQL queries are exactly one of those cases where functional expression of a problem outperforms the procedural expression, and that's why they're used where it matters.
Because neither of those are true.
You’ve conceded that SQL queries are one case where a functional approach is more ergonomic (after first asserting that the world is not functional, whatever that means). Why aren’t there other cases? Are you sure there aren’t other cases? One could argue that a functional approach maps more practically and ergonomically for the majority of general programming work than other mainstream approach.
No, I'm saying the functional abstraction doesn't work or is clunky in a lot of cases and that Haskell's approach of making it the core of the language is misguided (Lisp is less opinionated than Haskell for one).
> One could argue that a functional approach maps more practically and ergonomically for the majority of general programming work than other mainstream approach.
They could argue, but they would be wrong.
SQL works because it's a strict abstraction on a very defined problem.
Functional is great when all you're thinking about is numbers or data structures.
But throw in some form of IO or even random numbers and you have to leave the magical functional world.
And you know why SQL works so fine? Because there are a lot of people working hard in C/C++ doing kernel and low-level work so that the "magic" is not lost on the higher level abstractions. And can you work without a GC?
Functional programming certainly doesn't work literally everywhere, but to say Haskell's design is "misguided" is your opinion, and it's one that some of the biggest names in the industry reject. How much experience do you have designing programming languages? Or even just building non-trivial systems in Haskell? Judging by the evident ignorance masked with strong opinions I'd say around about the square root of diddly-nothing.
> But throw in some form of IO or even random numbers and you have to leave the magical functional world.
Wrong. Functional programming handles IO and randomness just fine.
> And you know why SQL works so fine? Because there are a lot of people working hard in C/C++ doing kernel and low-level work so that the "magic" is not lost on the higher level abstractions
Are you suggesting there aren't a lot of people working hard on GHC? Because if you are — and you seem to be — then again you would be wrong.
Exactly. I don't know why Haskell fanboys insist on abstracting us so far from the machine. Declarative programming is really unhelpful because it says nothing about the order in which code executes.
We live in a mutable physical universe that corresponds to a procedural program. One thing happens after another according to the laws of physics (which are the procedural program for our universe). Electrons move one after another around circuits. Instructions in the CPU happen one after another according to the procedural machine code.
The universe would never consider running 2020 before 2019 and a CPU will never execute later instructions before earlier instructions.
Haskell fanboys talk about immutable data structures like it's beneficial to go back in time and try again. But it's a bad fit for the CPU. The CPU would never run some code and then decide it wants to go back and have another go.
All of this is possible only with careful bookkeeping of the microarchitectural state. I agree the CPU is a stateful object. But even at the lowest level of interface we have with the CPU, machine code, there are massive gains from moving away from a strict procedural execution to something slightly more declarative. The hardware looks at a window of, say, 10 instructions, deduces the intent, and executes the 10 instructions in a better order, which has the same effect. (And yes, it's hard for me to wrap my head around it, but there is a benefit from doing this dynamically at runtime in addition to whatever compile-time analysis.) In short, it is beneficial to go back and have another go.
This was demonstrated also in https://snr.stanford.edu/salsify/. If you encode a frame of video, but your network is all of the sudden to slow, you might desire to encode that frame at a lower quality. Because these codecs are extremely stateful (that's now temporal compression works), you have to be very careful about managing the state so for can "go back and have another go".
I am less confident about it, but what you say about the universe also seems wrong. What physical laws do you know take the form of specifying the next state in terms of the preceding state? And literally many of them are time-reversible.
Not sure what the parody was in computing 2020 before 2019.
I believe it is because abstractions are the way we have always made progress. Is the C code that's so close to the machine not just an abstraction of the underlying assembly, which is an abstraction of the micro operations of your particular processor, which in turn is an abstraction of the gate operations? The abstractions allow us to offload a significant part of mental task. Imagine trying to write an HTML web page in C. Sure it's doable with a lot of effort, but is it as simple as writing it using abstractions such as the DOM?
> We live in a mutable physical universe that corresponds to a procedural program. One thing happens after another according to the laws of physics (which are the procedural program for our universe).
You just proved why abstractions are useful. "One thing happens after another" is simply our abstraction of what actually happens, as demonstrated by e.g. the quantum eraser experiment [1][2].
[1] https://en.wikipedia.org/wiki/Delayed-choice_quantum_eraser
>The abstractions allow us to offload a significant part of mental task
Edge/corner cases in our abstractions is also how propagation of uncertainty[1] happens. You can't off-load error-correction [2]
[1] https://en.wikipedia.org/wiki/Propagation_of_uncertainty
https://en.wikipedia.org/wiki/Superscalar_processor
> a CPU will never execute later instructions before earlier instructions
https://en.wikipedia.org/wiki/Out-of-order_execution
> The CPU would never run some code and then decide it wants to go back and have another go
Even C abstracts the machine, the ISO C standard is written for an abstract machine, not high level Assembly like many think it is.
Abstracting the maching is wonderfull, it means that my application, if coded properly, can scale from a single CPU to a multicore CPU + coupled with GPGPU, distributed across a data cluster.
Have a look at Feynamm's Connection Machines.
Except thanks to a compile-time optimization.
The reason SQL (really - relational algebra) works so well is precisely because relational data is strongly normalized [1].
But the data is only a model of reality, not reality itself. And when your immutable model of reality needs to be updated strong normalisation is a curse, not a blessing. The data structure is the code structure in a strongly-typed system[2]
Strong normalisation makes change very expensive.
[1] https://en.wikipedia.org/wiki/Normalization_property_(abstra...
Have you watched the talk "Are we there yet?" by Rich Hickey? He makes a convincing case, referencing the philosophy of Alfred North Whitehead, that "the world is functional".
http://www.infoq.com/presentations/Are-We-There-Yet-Rich-Hic...
Where this falls short is domains that are extremely ill-suited to keeping track of past states over time (his identity idea) simply because it would break performance or be hard to model in those terms, say simulations, game development, directly working with hardware and so on.
Much of his argument relies on the GC and internal implementation being able to optimise away the inefficiences of the functional model that needs to recreate new entities over and over, but this simply is not always enough.
This also is very obvious if you look into the domains where Clojure or other declarative functional languages have success, it's almost always business logic / data pipeline work.
edit: And in fact a lot of his most salient points aren't really as much about functional programming as they are about lose coupling and dynamic typing. A lot of his criticism of state and identity in languages like Java isn't related to Java not being functional, it's related to Java breaking with the idea of late binding and treating objects as receivers of messages rather than "do-ers".
Performance seems to be the problem there more than the model not fitting. And Rich’s answer would probably be that Clojure isn’t the right tool for those tasks in the same way that any general-purpose GC’d language isn’t.
Modeling a game or sim as a successive series of immutable states sounds great to me, so I’m curious where you see a mismatch with them. Abstracting hardware properties this way sounds useful too, but I’ve not worked with it enough to comment.
because I don't really think the functional model describes it in an intuitive way. You can model a sim or game at a high level like worldstate1 -> worldstate2 etc.. but it doesn't really tell you much, because often you don't really care what the state was a second ago anyway in particular not in its entirety, and because at that high level of abstraction you don't really get any useful information out of it, so there's no point in tracking it in the same way it makes sense to track a medical history or a bunch of business transactions.
Rather instead of thinking of games or sims as high level abstract transitioning states we tend to reason about them as a sort of network of persistent agents or submodules and that lends itself much closer to a OO or message based view of the world.
I think in many systems that are highly complex and change very incrementally reasoning about things in terms of functions doesn't really tell you much. You can for example reason about a person as like say a billion states through time but there's not much benefit to it at least to me.
I agree that looking at a whole worldstate at once is unlikely to be useful. But I do see great value in keeping state changes isolated to the edges of a system, and acting upon it with pure functions. If you have the means to easily get at the piece of state tree that you’re interested in, you can reason more clearly about how each piece of a simulation reacts to changes by just feeding the relevant state chunk to it and seeing what comes back. That takes more work to set up or repeat if each agent tracks its own internal state.
I haven’t used Clojure to make a game before, so I’m speculating here. I find myself avoiding internal state by habit lately, though of course “collections of relevant functions” are valuable tools. I just lean towards using namespaced functions instead of objects with methods.
The case is convincing, but it requires you to reject your own, human, faculties.
Makes the use/expression of language rather awkward when you can't remember any words.
Why not?
To give a functional Haskell flavoured example, I can use the Reader and Writer monads (which are functional) to create a whole bunch of operations which write to and read from a shared collection of data. That feels a lot like memory to me.
Indeed, the Reader monad is defined as:
> Computations which read values from a shared environment.
I just don't understand the whole "you can't have memory / order of operations / persistence / whatever else" as an argument against functional concepts when they have been implemented in functional ways decades ago. The modern Haskell implementation of the writer monad is an implementation of 1995 paper.
Edit: it looks like who I responded to doesn't actually want to have a reasonable discussion, but for anyone else reading along, it's entirely possible to have functional "state" or "memory" - what makes it functional is that the state / memory must be explicitly acknowledged.
Trying do dismiss functional computation in this way is essentially a no true Scotsman; functional computation is useless because it can't do X (X being memory or persistence or whatever), but when someone presents a functional computation that does do X, it's somehow not a "real" functional computation precisely because it does X. Redefining functional computation as "something that can't do X" doesn't help anyone, and doesn't actually help with discussing the pros and cons of functional programming since you're not actually discussing functional computation but some inaccurate designed-to-be-useless definition mislabeled as functional computation.
Isn't state/memory assumed by default when talking about computation?
What kind of computations you can perform on a Turing machine without a ticker tape?
What are you applying your α-conversion and β-reduction operations to?
It sounds mutable.
There you go. No mutation!
It's what all data storage systems do.
An immutable data store sounds pretty useless.
https://en.wikipedia.org/wiki/Persistence_%28computer_scienc...
Once again, you are free to ignore the things you don’t understand. Your trolling is mostly harmless.
Is that why you are ignoring the complexity behind persistence/mutability/state?
Even the Abstract Turing machine has ticker tape you know...
My interpretation is the exact opposite. Newtonian physics suggests the fundamentally deterministic world that QM can't because in the latter the only thing that is deterministic is probabilities.
Programming languages aren’t about the final result but about how you decompose the result into modular abstractions.