5 ms·
It'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
by pflanze 5y ago
It'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 ...
- slver 5y agoI'm not deep into Haskell, but isn't the interpreter monad pattern effectively a language within the language that acts in a very conventional procedural way for interacting with IO and other external concerns? I just wonder... does Haskell really need syntactic segregation for this, and how is that better than any language which can declare/enforce pure functions/modules without the entire language being like that by default.
- tome 5y agoWell, give it a go! Or alternatively, look for languages that have been successful in enforcing any kind of purity and that also permit unrestricted use of higher order functions.
- slver 5y agoIt's very hard to make Haskell look attractive to me, I deal with open systems (i.e. systems which interact with many other heterogenous systems which evolve in time), and Haskell is optimized for precisely the opposite case (a walled garden built out of elaborate types for verifying correctness). Haskell is the weird introvert guy in an extrovert world.
- valenterry 5y agoInteresting - for me it is the opposite. Non-functional languages usually work better if there is no concurrency involved. And 3rd party systems always introduce a certain amount of concurrency, sometimes more, sometimes less. I would say pure FP languages such as Haskell are actually the best for such a case. Because in these languages the order/timing of lines of code are decoupled from the execution order/timing.
- slver 5y ago> I would say pure FP languages such as Haskell are actually the best for such a case. Because in these languages the order/timing of lines of code are decoupled from the execution order/timing. ... That's good in your opinion?
- valenterry 5y ago> For all practical purposes it is used to write code that exerts (local) side effects into the state maintained by the state monad. Yes, but as long as this is done with only pure expressions, then the whole program is pure functional - that is what the definition is about. > 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? The guarantee or at least convention of referential transparency for every expression has benefits. It means I as a developer can make certain assumptions about code that I could not make otherwise. I can do certain refactorings and changes while being sure that it will not change the program semantics. As soon as parts of the program is not pure anymore, I know have to always re-assure myself that I'm currently working with the pure part of the code. Same for any tooling that I build. As I said, you can make that choice and sometimes it is the best thing to do - but you cannot call your application "pure functional" anymore when you do.