Comment by sparkie

3 days ago

Haskell can do the same kind of thing (local mutation), using the ST monad.

It's usage is almost equivalent to using IORefs, except we can escape ST using runST to get back a pure value not in ST, which we cannot do for IO because there is no `IO a -> a`.

There's no requirement to contain ST to a single function - we can split mutation over several functions, provided each one involved returns some `ST a` and their usage is combined with >>=.

https://dl.acm.org/doi/pdf/10.1145/178243.178246

That's right. Locally scoped mutable memory in Flix is very similar to the ST Monad. The two major differences are: (a) Flix is in direct-style vs. monadic style and (b) we use a type and effect system.

Note that there is no requirement that all mutation must occur within a single function. The requirement is that once you leave the lexical scope then all mutable memory associated with that scope become unreachable. Mutation can certainly span over multiple functions.