The value in a monad is that it allows you to work with pure data transformations (functions), which can then be reused, composed, tested, used in isolation and then deal with the side-effect later when you really need it. If you think about the monadic type as a container, it allows you to apply transformations while not pulling the values out of that container (think data-structures). If you think about a monad as a context, it allows you to apply transformations while keeping the context (think Future/Promise).
The call of a side-effecting function of course it has a well-defined value and I don't think there's anybody knowledgeable enough in FP to deny that. Problem is - there's data missing in the representation of side-effecting operations. For example, take a statement like this:
x = x + y
As a matter of fact, this makes no sense mathematically, because there's data missing from the above representation, as it really means this (where i, j and k are moments in time):
x(i) = x(i - j) + y(i - k)
So time is actually an implicit parameter here that you've got no control over. The above representation makes even more sense when studying the architecture of CPUs. And as a side-effect, the old value of "x" gets lost and so if anybody else holds a reference to "x", then that reference will point to an entirely different value, an event that can happen at arbitrary points in the future, so you could say that the whole world changes after an operation like that. Since concurrency is often brought into the picture, I think it's fairly easy to see how this can create problems in terms of our capability to reason about the logic we read or write.
Also, if we think about side-effecting components (say, mutable objects), the functional behavior of such a component ends up depending on its history, history that's in no way explicit. Variables are buckets or places. Immutable values are facts that can be compared. E.g. 2 references to mutable things cannot be considered equal, unless they point to exactly the same memory location, otherwise equality (as defined in the programming languages we are using) is broken and a constant source of gotchas.
That link you posted argues that the way we are using the term "referential transparency" today for programming languages is different from its original meaning, but I'm arguing that the original meaning is not relevant for programming languages. There's no point in arguing that a side-effecting function call in C does have a well-defined "value".
Yes, the output of a side-effecting function can be considered a value, but you can't treat it as a value.
The call of a side-effecting function of course it has a well-defined value and I don't think there's anybody knowledgeable enough in FP to deny that. Problem is - there's data missing in the representation of side-effecting operations. For example, take a statement like this:
As a matter of fact, this makes no sense mathematically, because there's data missing from the above representation, as it really means this (where i, j and k are moments in time): So time is actually an implicit parameter here that you've got no control over. The above representation makes even more sense when studying the architecture of CPUs. And as a side-effect, the old value of "x" gets lost and so if anybody else holds a reference to "x", then that reference will point to an entirely different value, an event that can happen at arbitrary points in the future, so you could say that the whole world changes after an operation like that. Since concurrency is often brought into the picture, I think it's fairly easy to see how this can create problems in terms of our capability to reason about the logic we read or write.Also, if we think about side-effecting components (say, mutable objects), the functional behavior of such a component ends up depending on its history, history that's in no way explicit. Variables are buckets or places. Immutable values are facts that can be compared. E.g. 2 references to mutable things cannot be considered equal, unless they point to exactly the same memory location, otherwise equality (as defined in the programming languages we are using) is broken and a constant source of gotchas.
That link you posted argues that the way we are using the term "referential transparency" today for programming languages is different from its original meaning, but I'm arguing that the original meaning is not relevant for programming languages. There's no point in arguing that a side-effecting function call in C does have a well-defined "value". Yes, the output of a side-effecting function can be considered a value, but you can't treat it as a value.
Of course, we can always argue semantics.