Hacker News new | ask | show | jobs
by crimsonalucard 2353 days ago
A different way of thinking of abstraction or just a feeling of elegance or a feeling of power is not a sufficient explanation for why Haskell is so great.

People want definitive and theoretically correct answers not talking points for a philosophical debate on programming styles.

Why is typed functional programming measurably better than procedural? Why is it better than OOP? Definitive answers are in demand not exploratory experiences.

4 comments

Definitive answer: sum/union types [0] and currying/partial function application [1]. Between the two, almost anything you write becomes very easy to adapt to new requirements. Anyone who has done a medium to large scale fp project can attest to this.

If you want to be pedantic, currying and partial application are separate concepts, but I've never seen an fp lang implement one without the other. Note that I linked to this f# blog because I think its example-forward approach is clearer than most fp documentation I've read.

[0] https://fsharpforfunandprofit.com/posts/discriminated-unions...

[1] https://fsharpforfunandprofit.com/posts/currying/

Sum and product types are essential for programming. After you have used a language with them you will miss them dearly in any other language you use.

Typeclasses and traits (if you're writing Rust) coupled with ad hoc polymorphism are a succinct and beautiful method of abstraction. You will miss them also in almost any other language.

Those features in a language (functional or not) will let you confidently refactor code, and (IMO) will lead to less mistakes and better abstractions.

Why does "Typed Functional Programming" have to be measurably "better" then OOP or procedural programming in order for Haskell to be considered a good language?

All those questions at the end of your comment can be turned around the other way and are equally valid and unanswerable.

Why use it if it's not measure-ably better on some metric? It's important because we should only use things if they are better or the same. Not if they are worse.

Sure, there are tradeoffs but if you quantify all tradeoffs something usually comes out better.

If you can objectively measure the quality of a program (in a non-bs) way, you could probably make millions. There are whole industries around code health metrics.
I doubt I could make billions. I don't think it's that hard.
> Why is typed functional programming measurably better than procedural? Why is it better than OOP? Definitive answers are in demand not exploratory experiences.

Functional code tends to be shorter than procedural code. This allows you to think in bigger steps. For example, to read whitespace-separated numbers from stdin and print out their sum, in haskell you could write:

    main = interact $ show . sum . map read . words
This uses very generic haskell functions to put the input into a list of strings, read each string as a number, sum the numbers and show the sum as a string.

It seems to me that the equivalent procedural code would be much longer.

Haskell's type system keeps track of what's going on and alerts you when you try to do something that doesn't make sense. For example, if you leave out the "read" function above, you would be trying to sum strings instead of numbers. Haskell's type checker would complain at compile time. This enables you to program at a high level without having to debug run-time errors because of type mistakes.

>Functional code tends to be shorter than procedural code

Shorter is one metric that FP "tends" to be better at. But it's not definitive. Who says procedural programs can't be shorter? And also is shorter necessarily better? Also does it come at the cost of readability? Actually let's not get into readability as it's not exactly measure-able.

>Haskell's type system keeps track of what's going on and alerts you when you try to do something that doesn't make sense.

Algebraic Type systems are indeed a measure-able metric when you measure correctness, amount of errors or total possible programs you can write. It restricts the code you can compile to be correct from a typed perspective. Meaning that out of all the possible programs you can write, Haskell allows you to write less programs in the sense that it stops you from writing certain incorrect programs.

However, ADT's can be used in procedural programs or OOP programs as well. See Rust.

What I want to know is specifically about the functional programs. In the functional programming paradigm what is the quantify-able metric that makes it definitively better?

> However, ADT's can be used in procedural programs or OOP programs as well. See Rust.

Rust isn't OOP. Funnily, it's type system is pretty much the same as Haskell's but stops just before higher kinded types.

Ignoring type systems and just looking at functional vs imperative, the advantage for functional is immutability making functions easier to reason about. Haskell in particular is also lazy, and therefore enables you to not be concerned with evaluation order.

Thanks for letting me know rust isn't OOP. I never said it was. Funnily.

>Ignoring type systems and just looking at functional vs imperative, the advantage for functional is immutability making functions easier to reason about. Haskell in particular is also lazy, and therefore enables you to not be concerned with evaluation order.

Sans the part about laziness, for which the formal term is "normal order evaluation" FYI, OOP guys say the exact same thing about objects word for word.

I don't see how that could be true, as OOP is inherently about encapsulating mutation not preventing it. The problem with OOP is you're also free to alias mutable objects.

> Sans the part about laziness, for which the formal term is "normal order evaluation"

If you want to be pedantic, Haskell is 'call by need', not 'normal order'.

Sure but this is what they say and what they believe. Literally. Armies of programmers believe this and your statement won't convince them.

It always goes into philosophical mumbo jumbo. I'm looking for quantitative and logical proofs that say definitively why functional is better. You do see how your statement will just trigger a vague retort from an OOP guy which will trigger a bunch of other vague retorts and counter examples from you. The end game is it goes nowhere.

If I want to be pedantic, the official term is normal order. You are wrong on this. See SICP chapter 1.

> In the functional programming paradigm what is the quantify-able metric that makes it definitively better?

It seems extremely unlikely that you'll ever find a satisfactory answer to this, because any advantage a programming language paradigm gives you is either going to be in terms of programming language theory (which you rejected up-thread), or in terms of developer experience and productivity (whatever _that_ means). However, any rigorous study of those latter categories is likely going to be seriously confounded by their variability due to things which are _not_ related to language paradigm, such as organizational concerns, the language's tooling and ecosystem, the problem domain, the skill and experience of individual developers, &c &c. None of these things is straightforward to control for, and I'd be extremely skeptical of any quantifiable metric someone shows me that purports to show clear wins in real-world software development based on language paradigm of all things.

> is either going to be in terms of programming language theory

Programming language theory does not study "advantages;" it's simply not a question it asks, let alone answers. The theory is concerned with what properties certain formal systems have. It cannot, nor does it attempt, to assign those properties a value, just as mathematics does not ask or answer whether prime numbers are better than composite numbers.

> None of these things is straightforward to control for, and I'd be extremely skeptical of any quantifiable metric someone shows me that purports to show clear wins in real-world software development based on language paradigm of all things.

Maybe, but that doesn't matter. You cannot claim that you're providing a significant benefit and in the same breath say that it isn't measurable. An advantage is either big or not measurable; it can't be both. If you say that the benefit of the language is offset by the bad tooling, then you're not really providing a big benefit. If and when the tooling catches up, then it's time to evaluate.

But maybe not. I find it very dubious that significant differences are not measurable in an environment with such strong selective pressures for two reasons: 1. it doesn't make sense from a theoretical perspective -- adaptive traits should be detected in a selective environment, and 2. it doesn't fit with observed reality. We observe that technologies that truly provide an adaptive benefit are adopted at a pace commensurate with their relative adaptability; often practically overnight. The simplest explanation from both theory and practice to why a technology does not show a high adoption rate is that its adaptive benefit is small at best.

>Programming language theory does not study "advantages;" it's simply not a question it asks, let alone answers. The theory is concerned with what properties certain formal systems have. It cannot, nor does it attempt, to assign those properties a value, just as mathematics does not ask or answer whether prime numbers are better than composite numbers.

I think we can go deeper than this. There are properties of well designed programs that can be measured to be numerically higher or lower than poorly designed programs. Under this mentality "better" is simply a word with no meaning that is describing a number. It is the human that has the opinion that the higher (or lower) number is a "good design."

The question is what is that number and how do you measure it? For example one number off the top of my head: lines of text. Another better number is the amount of functions. Both of these numbers have flaws so maybe a better number is given a (high level language) and a (program written in assembly language); what is the largest number of high level language primitives you can use to recompose an identical program?

(high level language primitives)/(low level language primitives)

As the ratio approaches 1 we are achieving maximum flexibility as the high level language is injective to the low level primitives. As the ratio approaches zero we are reducing complexity at the cost of flexibility (we reason about less primitives). If the ratio exceeds one then we are creating excess primitives.

Maybe the better designed language/paradigm can has primitives that can used to drive that ratio back and forth from 0 to 1. A poorly designed language is one with a ratio of 4.5 or 0.0001.

So something more advanced but along the lines of this rudimentary and rough outline is certainly possible in my mind.

>But maybe not. I find it very dubious that significant differences are not measurable in an environment with such strong selective pressures for two reasons: 1. it doesn't make sense from a theoretical perspective -- adaptive traits should be detected in a selective environment, and 2. it doesn't fit with observed reality. We observe that technologies that truly provide an adaptive benefit are adopted at a pace commensurate with their relative adaptability; often practically overnight. The simplest explanation from both theory and practice to why a technology does not show a high adoption rate is that its adaptive benefit is small at best.

Yeah I agree. Additionally we're not dealing with the real world here with billions of variables. This isn't a computer vision problem. Assembly language, FP and OOP have a countable amount of primitives. It is amenable to theory and measurement.

>(which you rejected up-thread)

Where did I reject programming language theory? You mean type theory? I didn't reject it. I said it doesn't apply to functional because ADT's can be used on most programming styles outside of FP.

>None of these things is straightforward to control for, and I'd be extremely skeptical of any quantifiable metric someone shows me that purports to show clear wins in real-world software development based on language paradigm of all things.

Don't account for those things. Account for what can be measured. Cut through all the frosting and get to the main point. What is the exact definition of a well designed program when we don't factor in opinionated things like readability? At it's core their must be fundamental properties of a shitty program and a well designed one that exist outside of opinion and is pretty much universally agreed upon.

I feel to be realistic you have to show a program with failure scenarios. That is at least where i struggle with FP. Like what happens if a user enters a non-numeric value and i want to echo back a warning and get a correction, before continuing?
It's shorter in Python:

  sum(int(n) for n in input().split())
I'd argue it's an awful lot clearer, too.

Edit: A more functional version is shorter still, but I think not worth the readability cost:

  sum(map(int, input().split()))