4 ms·
>The Python code has the added advantage of actually being correct, assuming that the intended behaviour really is to add up the total of all entered numbers ov
by runT1ME 13y ago
>The Python code has the added advantage of actually being correct, assuming that the intended behaviour really is to add up the total of all entered numbers over time as the output suggests.
Only in a single threaded environment. However, concurrently, the Haskell code stays correct in a concurrent environment while your python code has bugs.
Extrapolate a bit, and think about how many python functions may be slightly less trivial than yours and yet still have the same concurrency issues...
- dllthomas 13y agoYou mean the Haskell code stays equally incorrect in a concurrent environment...
- asdasf 13y agoWhat is incorrect about it?
- tel 13y agoThe thread op assumed that the code was supposed to accumulate the amounts ever entered. The Haskell code doesn't accumulate, it adds you input to the prior state, prints that sum, then stores your input, not the sum as the next state. Of course, that's just a (likely true) assumption of what the behavior was supposed to be and it extrapolates far from the point. The example didn't really intend to show off a particular behavior but instead the interweaving of effects.
- Chris_Newton 13y agoThe example didn't really intend to show off a particular behavior but instead the interweaving of effects. Indeed. My point was not to nitpick an interesting article. I was trying to illustrate how making so many details explicit in Haskell has a real, practical downside: what seems to be an obvious logic error had slipped through, where it surely would have been spotted easily in the simpler Python code. Moreover, no-one had even mentioned this possible bug after a couple of hours and dozens of posts here, though of course that could just be because no-one else felt this point was important enough to make rather than because they hadn’t noticed.
- dllthomas 13y agoFWIW, I tend to prefer using modify rather than set wherever that makes sense, which would make this particular bug harder to express.
- tel 13y agoYeah. I didn't follow your point since I didn't feel like this was a terrifically idiomatic example. I felt like the bug was equally easy to catch in either expression.
- nightski 13y agoNo offense but you failed miserably. If you were trying to reproduce the python code in Haskell, the example is not what you would write. This is a 1 liner in Haskell. The two examples do not represent the same thing.
- Chris_Newton 13y agoThe two examples do not represent the same thing. This is a claim I don’t understand. They are both simple examples of representing an algorithm that maintains state in their respective languages. Of course you could write it as a one-liner using a different style in Haskell, and in various imperative languages for that matter. However, my point was that making these monadic abstractions explicit everywhere in Haskell does add weight to the code. That continues to be true for more complicated stateful code that can’t be rewritten as a one-liner or expressed more elegantly using recursion anyway.
- asdasf 13y agoIt is made explicit and verbose in that contrived example because it specifically an example of those things. I am having a really hard time believing that you genuinely don't understand this obvious fact.
- Chris_Newton 13y ago
- dllthomas 13y ago"Total: " implies that it's meant to be summing the input values. It's actually only summing the current and the previous, because it puts back val not (val + state).
- Chris_Newton 13y agoContrary to the hype, I think plenty of useful code does still run in a single-threaded environment, so I find your argument unconvincing. That said, even in an environment with concurrency, I’m not advocating uncontrolled state changes as typified by current imperative programming languages. I’m arguing that we could benefit from the robust theory underlying languages like Haskell, but used more transparently so the developer only has to worry about it when it matters. For example, you could be running a second thread in parallel with the one we’re looking at here, but if its effects are constrained to replying to a network-supplied request for the current time and reading the system’s clock, it doesn’t matter at all that our interactive adder is running at the same time. These effects affect different, independent resources and will never interact, so there is no benefit to cluttering either code path with extra details. What I’d really like to see is a language that could understand those resources and how they are affected by each thread in terms of reads and updates. I want it to stop me from modifying the code later so that it accidentally becomes vulnerable to interactions that I’m not fully controlling. I want it to provide me with tools to specify how potential interactions should be handled, in a way that is systematic and robust but otherwise as simple as possible, and that can be applied at whatever level of my design makes the most sense. Research into type and effect systems is addressing challenges like these, but I’m hoping that when the dust settles, the final version will look a lot more like Python with a few strategically placed annotations than Haskell where these implementation details are in your face all the time (even if most of the time you don’t actually need to worry about them).
- runT1ME 13y ago>I want it to stop me from modifying the code later so that it accidentally becomes vulnerable to interactions that I’m not fully controlling. I want it to provide me with tools to specify how potential interactions should be handled, in a way that is systematic and robust but otherwise as simple as possible, and that can be applied at whatever level of my design makes the most sense. That's...the state monad. The compiler tells you when you try to access it in a way that is not allowed. You have to be explicit with sharing.
- Chris_Newton 13y ago
- pekk 13y agoWhy are you having multiple threads share 'total' at all?
- millstone 13y agoI'm intrigued by the claim that the Haskell code is correct in a concurrent environment. If I run two copies of this function concurrently, won't they step on each others' toes as they fight over the file offset of stdin?