Comment by jorkadeen
3 days ago
In Flix all effects are tracked by the type and effect system. Hence programmers can know when a function is pure or impure. Moreover, pure functions can be implemented internally using mutation and imperative programming. For example, in Flix, one can express a sort function that is guaranteed to be pure when seen from the outside, but internally uses a quick sort (which sorts in place on an array). The type and effect system ensures that such mutable memory does not escape its lexical scope, hence such a sort function remains observationally pure as seen from the outside.
(I am one of the developers of Flix)
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.
What do you mean with 'cannot'? We have this in [0]
Do you mean "cannot do with safety guarantee"? Strangely enough, the haskell docs use the same language as you:
___
0. https://hackage.haskell.org/package/base-4.21.0.0/docs/Syste...
This sounds very nice!