
Thus quoth Joachim Durchholz at 13:58 on Wed, Apr 19 2017:
Am 19.04.2017 um 15:13 schrieb Sergiu Ivanov:
However, there are a couple big "backdoors", like the IO monad.
Well, it's so awkward that people don't *want* to use it.
Interesting point of view, I've never thought of the relative awkwardness of IO as of an educational measure.
Typechecking gives zero guarantees for functions of type IO (), for example.
That doesn't match what I hear from elsewhere. I don't know what is the cause for that difference though.
I'm probably shouting my "zero" too loudly. I wanted to say that, when the typechecker sees a function of type IO (), it only knows that it _may_ have side effects, but it cannot verify that these effects compose correctly with the effects coming from other functions in the IO monad. Of course, the return type IO () still gives a lot of information (e.g., it says the function is only useful for its side effects) and the type system will ensure that any computation actually using this function must be declared as (potentially) having side effects. Yet, you have no guarantees that such effects are composed correctly.
In fact, I believe having pure functions does not so much target removing state as it does making the state _explicit_.
Except State tends to make state implicit again, except for the fact that there *is* state (which might be actually enough, I don't have enough insight for any judgemental statements on the issue).
Well, a typical definition of State is parameterised in the type of the state, so you know what it is. Sure, a typical definition of State does not let you know whether and how the state was modified, but if one wants that information, one can "just" define a custom "StateLog" monad, for example, or even use Applicative to statically "record" the effects on the state (I hear that's one use of Applicative). -- Sergiu