12 ms·
> Functional Programming” doesn't have a precise definition at all It may be that different people mean different things when they talk about FP. I come from
by ahf8Aithaex7Nai 2y ago
> Functional Programming” doesn't have a precise definition at all
It may be that different people mean different things when they talk about FP. I come from the Haskell corner and from my point of view that's a completely insane claim, at least when it comes to pure FP.
[ ] Are you writing a procedure that just processes its arguments into a return value?
[ ] Does the procedure also operate on a non-static context?
[ ] Does the procedure generate additional side effects?
If you answer yes|no|no, you are programming purely functionally.
The formal litmus test is the question of whether your procedure actually fulfills the definition of a mathematical function with regard to the relationship between the arguments and the return value. If it also does not generate any side effects, it is a purely functional procedure!
Then you can apply the principles of mathematical composition of functions to the construction of programs. Purely functional languages force you to program this way by default and to use special constructs for everything that has to do with side effects: IO monad, algebraic effects, The Elm Architecture.
How are you supposed to program like this? This is where (in addition to the concepts mentioned above) the higher-order functions that everyone knows come into play: map, fold, filter, flatMap, ... If you only know these and their use in impure languages, as if this were nothing formally thought through, but just a programming style for hipsters, then I can understand how the impression arises that there are no precise definitions here.
In practice, the concepts are often very distorted or not understood at all. For many programmers, OOP mainly seems to mean that you get the drop-down list with completions in Rider when you press “.”.
- tome 2y agoI also come from the Haskell corner and I agree with roenxi. I don't think that FP is a well-defined concept, nor do I understand your characterization of pure FP. Let's take a simple program main = do v <- newIORef 0 let procedure = do n <- readIORef v print n modifyIORef v (+ 1) ... and have a look at the conditions you laid out * Are you writing a procedure that just processes its arguments into a return value? No, it has no arguments and its return value is just (), but it does more besides. * Does the procedure also operate on a non-static context? Yes, it operates v * Does the procedure generate additional side effects? Yes, it prints to the terminal. So I have answered no | yes | yes, the exact opposite of what I should have to be classed as doing pure functional programming. You might say "Ah, but the return value of `procedure` is not (), it's IO ()", but I don't see that that changes anything. I can write my entire program in IO if I want, in a way that's hard to distinguish from having written it in, say, Python. Is that not pure functional programming, despite the fact that it's being carried out in Haskell? Then you might say "Ah, but the difference is that you could have written your program purely, without IO". But again I fail to see how that differs from Python. I can write programs that don't do any IO in Python too. So what is it that makes Haskell a pure functional language and Python not? My response to all this is that the notion of "pure" is very unhelpful and the correct way to describe this property that Haskell has is "referential transparency", that is let x = rhs in ... x ... x ... has the same result as ... rhs ... rhs ... regardless of how many times (or zero) x occurs.
- ahf8Aithaex7Nai 2y agomain is never pure. Your `procedure` is also not pure (and also not referentially transparent). You can write impure code in Haskell, which your example demonstrates very well. But then it is necessarily IO code. Non-IO code, on the other hand, is always pure (and referentially transparent). > but I don't see that that changes anything It changes everything, but I can't explain it any better than I did above. > So what is it that makes Haskell a pure functional language and Python not? If you give me a Haskell procedure `f1 :: Int -> Int` without showing me the content, I still know that it is referentially transparent and pure. If f1 evaluates x to y once, I know that it ALWAYS evaluates x to y. If a main program in which f1 is used generates a screen output, for example, I can safely exclude f1 as the source of this side effect. If you give me a function `f2 :: Int -> IO Int` instead, I can't draw all these conclusions. In Python, these conclusions would be invalid from the start. Now you can say, “So what? Who cares?” But it helps me enormously when designing and structuring programs, understanding programs, localizing program behavior, etc. If you don't see any added value in this distinction (ensured by the compiler), we don't have to argue about it. But I simply cannot agree with you that this does not represent a conceptual and formally justified difference between Haskell and Python. Of course you can program purely functionally in Python. Just as you can program in a dynamically typed language as if you were dealing with static data types. Or in Java without throwing exceptions and null references around everywhere. Or in C without segmentation faults. These are not normative or moral comparisons, but other examples of the fact that you can of course program in such a way that the code has certain properties, even if the compiler does not secure these properties. The question is whether you want that.
- tome 2y ago> main is never pure. Your `procedure` is also not pure Ah, it's possible I misunderstood you. I missed that you said "Purely functional languages force you to program this way by default". I mistakenly assumed you were saying that in a purely functional language you can only program purely. So you are saying that Haskell is a pure functional language, but you can also write non-pure things in it? So being a "pure language" is more a case of what sort of style is encouraged rather than what sort of style is possible? > (and also not referentially transparent) Interesting. Could you explain what you mean by that? (The definition of referential transparency that I know doesn't apply to functions but to languages.) > You can write impure code in Haskell, which your example demonstrates very well. But then it is necessarily IO code. Non-IO code, on the other hand, is always pure (and referentially transparent). That's interesting. How do you distinguish these two pieces of code: f = do v <- newIORef 0 modifyIORef v (+1) readIORef v g = do v <- newSTRef 0 modifySTRef v (+1) readSTRef v is the former impure and the latter pure? Or are both impure? > So what is it that makes Haskell a pure functional language and Python not? If you give me a Haskell procedure `f1 :: Int -> Int` without showing me the content, I still know that it is referentially transparent and pure ... In Python, these conclusions would be invalid from the start. Do you mean because of the type? If not, I don't understand what distinction you're drawing, and what makes the conclusions invalid for Python. If so, then does a pure language have to be typed? Would it be impossible for a pure language to be untyped? > Now you can say, “So what? Who cares?” But it helps me enormously when designing and structuring programs, understanding programs, localizing program behavior, etc. If you don't see any added value in this distinction (ensured by the compiler), we don't have to argue about it. We don't have to argue about it. I program in Haskell every day and reap the benefits :) > But I simply cannot agree with you that this does not represent a conceptual and formally justified difference between Haskell and Python. I agree there's a conceptual and formally justified difference between Haskell and Python. I just don't agree with you about how to characterize it :) To reiterate my characterization, it is that Haskell has "referential transparency", that is let x = rhs in ... x ... x ... has the same result as ... rhs ... rhs ... regardless of how many times (or zero) x occurs. That's it! Nothing to do with "purity", "IO", "processing arguments", "non-static contexts" or "side effects". Now I may be wrong. That's why I'm trying to understand what you think the characterization is. But so far I have never discovered a benefit of programming "purely" in Haskell that is not ultimately a consequence of what I call "referential transparency" above. Do you know one?