3 ms·
OK, so you're on about a physical/temporal separation of IO and logic: the logical calculations can be performed separately to the IO actions, and vice versa.
by chriswarbo 11y ago
OK, so you're on about a physical/temporal separation of IO and logic: the logical calculations can be performed separately to the IO actions, and vice versa.
I view that as pretty trivial though; it's just a case of switching out the language's IO primitives, which are effectively free variables. With most "large" languages (Java, Haskell, etc.), the implementations are usually gnarly enough to make such substitution a significant engineering accomplishment, but that's an artefact of the situation, not the approach. As an analogy, the task of fitting corrective optics to the Hubble space telescope was only difficult because it was the Hubble space telescope; fitting adaptive optics is trivial enough that bespectacled children do it every day.
In light of this, I think that disentangling mixed-up definitions is a much more important and interesting problem. It's non-trivial to extract pure computations from imperative code (whether they're written in Java, or Haskell, or whatever), yet there is a great potential benefit for improving code, in terms of understandability, modularity, re-use, maintainence, etc. The fact that pure code is easier to test, or that side-effects can be substituted for the purposes of tests, is really a minor point in comparison. They are workarounds for running code which has too many responsibilities. Much better to avoid the problem in the first place by writing separate code for separate concerns.
- pron 11y agoYes, I agree that it's better to write good code than bad code :) Clear separation of concerns is an important aspect of good code, and every language teaches this practice. I don't think Haskell has any advantage there. I also think -- and this is probably a point of contention -- that the way Haskell separates pure computation from side-effects is a bit arbitrary. Haskell defines computation in a way similar to lambda calculus, which designates as impure any change to something which may then affect a function's result not through its arguments. In short, it equates the mathematical notion of the function with the software notion of the subroutine. Haskell subroutines are mathematical functions, period (well, except for unsafe etc.). I don't think that this is the best way to describe code, or to define separation of concerns (It also makes Haskell jump through hoops when it deals with things that are natural for computation but don't fit well with the notion of a mathematical function). A good separation of concerns in Haskell is not necessarily the best organization for Java/Python.