4 ms·
> FP means that every expression (= part that can be evaluated) is referential transparent. Most real-world programming requires handling of side effects somew
by pflanze 5y ago
> FP means that every expression (= part that can be evaluated) is referential transparent.
Most real-world programming requires handling of side effects somewhere, so such programs have parts which are not referentially transparent.
It's why I distinguished between "core" and "meat" in my other response. Functional programming languages offer features that help making a larger part of the program referentially transparent (and, optionally, to ensure that property in the types).
> Nowadays the word "functional" is used different from the original meaning (which some now call "pure functional")
I don't think the meaning changed, just the tools offered and the scope of the support they offer to achieve referential transparency (pure functions). Early Lisp offered expression oriented programming which was a step towards it, but used dynamic scoping which isn't really helping. Later on both Lisps and ML offered lexical scoping. Then the purely functional trend came up via Miranda and (Clean and) Haskell, the latter encoding purity in the type system. In the last decade mainstream programming languages added functional programming features but are falling short in encoding purity in the types (just as Lisp never did), which means that it's (easily) possible for the abstractions offered (both functions but also libraries built on iterators) to not be referentially transparent, manual care (and/or culture) is required instead. The tooling doesn't help enough to guarantee referential transparency. But the core idea, the target of the efforts, is the same.
> Referential transparency implies immutability.
I didn't go into immutability in my other response because you can use mutation inside pure functions, as long as the effect doesn't leave the function. Building referentially transparent functions does not imply using immutable data structures or variable bindings inside.
- valenterry 5y ago> Most real-world programming requires handling of side effects somewhere, so such programs have parts which are not referentially transparent. That's not correct though. Look at Haskell (or even stricter Idris). This is real world application code that can do whatever Java, C++, ... can do, but it is pure functional and hence doesn't contain any non referentially transparent parts. Just because an application is written in a pure functional style does not mean that it cannot e.g. write into a database when it is executed. Of course many languages don't even allow to use a fully pure functional style. In that case, a more or less big functional "core" is the closest one can come to a pure FP style. > I didn't go into immutability in my other response because you can use mutation inside pure functions, as long as the effect doesn't leave the function. Sure you can do that and sometimes it is even the best practical solution. And the function might even be referential transparent - but your whole application is now not pure functional anymore, because a part of it is not referential transparent anymore. Hence: if an application has to satisfy the criteria of being "pure functional" then every expression must be referential transparent and hence no mutation can be used.
- pflanze 5y agoIt's funny that you defend your view using Haskell, as I was replying with Haskell in mind. If you use the state monad, you encode local side effects. Then you use runState in a function that has a non-monadic type--a pure function. Feel free to argue that the state monad is only having pure expressions because it can be represented using only pure functions and partial evaluation. For all practical purposes it is used to write code that exerts (local) side effects into the state maintained by the state monad. You can a function in say, OCaml, that fills an array via mutation using only function arguments to deduct the contents, and then returns that array. That function is pure (it exerts no side effects outside and is not exposed to side effects from the outside, its result value only depends on the function argument values). Yet how is that not using mutation, non-referentially transparent parts inside? You can write the same function with a mutable vector in Haskell (Data.Vector.Mutable, using the ST monad). How is it not exactly the same code as the one in OCaml except for the types that guarantee the purity? Yes, it may be using pure expressions underneath to guide the type system to enable the proof of purity. But does that change what I said? Both to the programmer and (after optimization) to the machine the code is using mutation. You can model mutation using only pure functions. That may be useful in some ways, but you can also take a C program, represent every memory address as an entry in a tree of immutable nodes, the outside world as an abstract entity with versions, and recreate it with only pure expressions. That may be what is useful in some contexts for developing proofs or to implement type systems, but is this relevant for a programmer interested in writing more functional programs? Why not just say that using ST is using local mutation (that the type system can guarantee will not leak outside) and be done with it?
- deleted 5y ago[deleted]
- tome 5y agoEquivocation about purity, referential transparency, mutability, side effects etc. is not very interesting. The operative point is that, in Haskell, firstly x = expression y = expression ... is the same as x = expression y = x ... and that, secondly x = expression ... is the same as ... when x does not appear in ... . Those are the important properties of Haskell (with regard to this discussion). Whether this advances the discussion is another matter ...