# Mutable Value Semantics Trend vs Immutability

**URL:** <https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619>\
**Category:** Uncategorized\
**Created:** [September 19, 2023, 5:39am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619 "2023-09-19T05:39:01Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Dato](https://avatars.discourse-cdn.com/v4/letter/d/b38774/32.png) [@Dato](https://discourse.haskell.org/u/Dato)\
**Post date:** [September 19, 2023, 5:39am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/1 "2023-09-19T05:39:01Z")

</div>

In functional programming, ~~purity~~ immutability is one of the concepts that people usually emphasize on. By purity, I understand as enforcing values in the program to be immutable, at least as a specification for the language user (this includes languages such as Koka-lang where as a backend optimization their values might get mutated once it is statically knowable that the reference is unique)

However, as I observe, in these recent years, a new trend (not that the idea is new, but it is the first time the idea gains significant attention from the public outside of academic I suppose) that I would conveniently label as _mutable value semantics_ (MVS for short), as borrowed from [Native Implementation of Mutable Value Semantics](https://arxiv.org/pdf/2106.12678.pdf) has occurred. The most noticeable events would be the rising of Rust, with its ownership and borrowing system. Also, [Hylo | The Hylo Programming Language (hylo-lang.org)](https://www.hylo-lang.org/) also catches my attention.

To be self-contained, here is what I mean by my umbrella term MVS:  
When calling functions on variables, the compiler does things more intelligently and tracks the change of state of the variables being used, instead of being overly optimistic like Haskell where variables are supposed to be unchanged, thus purity has to be enforced, or being overly pessimistic like usual imperative languages where statically analyzing the states is deemed infeasible in general.

Here is a simplest example, in Rust,

```haskell
fn use_it_up(x:String) {
    println!("I consume the {:?} now, you cannot use it any more!", x)
}

fn main() {
    let x = "123".to_string();
    use_it_up(x);
    use_it_up(x); // again
          // ^   
          //compiler would decide the x here 
          //is no longer usable, and complains
}

```

This code results in an error saying that I am attempting to use a moved value. (Well strictly speaking it is not _mutating_ values so my usage of the term MVS is bad but I emphasize on the fact that the state of the used variables in the expression is semantically changed after the function call, i.e., in this case, the value of `x` becomes moved).

In other more complex examples, the compiler might track whether the variables are getting referenced (borrow checker in Rust), or whether the variables will be put back, like `inout`.

If one has to get into a holy war between programming paradigms, I might say this feels like a comeback for imperative programming. But eventually, FP or IP, in terms of semantics (as opposed to syntax), I personally only care about how I communicate with the compiler, the library and the user. And MVS feels a much more nuanced way to do so compared to both worlds of the past (just assume it is ~~impure~~ mutability or just enforce ~~purity~~ immutability).

In fact, this line of trend totally moves me out of the ~~purity~~ immutability camp (never in tbh). It is probably better, instead of saying we should ban mutation because it causes all sorts of problems, to say that we should communicate our intention as clearly as possible to the compiler, the caller, and the callee so that when I mutate or want to keep a reference to a value, they can be noticed, so that they can leverage their tools to optimize, verify and modularize.

But in Haskell, the fundamental of it seems to prevent such addition? I want to know what the Haskell community thinks of these kinds of language features(?), whether it is actually good or bad compared to alternatives, its desirability and feasibility in Haskell.

---

<div class="post-metadata">

**Author:** ![qqwy](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/qqwy/32/1983_2.png) [@qqwy](https://discourse.haskell.org/u/qqwy)\
**Post date:** [September 19, 2023, 6:47am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/2 "2023-09-19T06:47:37Z")

</div>

I think that the recent developments with Linear Types might be up your alley.

`x %1 -> ...` means `x` has to be used exactly once inside the function. (Parts of it) cannot be discarded nor duplicated (unless they implement the `Consumable` resp. `Dupable` traits).

Because the compiler knows for certain that inside the function there will only be a single `x`, extra copies/memory allocation is prevented. In a sense, this makes `x` similar to an `inout` parameter from the paper except in a way that fits better with the rest of Haskell’s pure functional type system.

One disadvantage of linear types in Haskell (compared to e.g. Rust’s borrow checking) is that they are ‘opt in’, in the sense that they restrict the _callee_ (the contents of a function) but not the _caller_ from holding on to a copy of the data.

Thus, some slightly less beginner-friendly ‘callback style’ APIs have to be used to fully restric values to uniqueness. (example: [`Data.Array.Mutable.Linear.alloc`](https://hackage.haskell.org/package/linear-base-0.3.1/docs/Data-Array-Mutable-Linear.html#v:alloc)) and also if you want to use linear types to their full extent, you want to ‘enter linear land’ very early in your program.

But while the ecosystem around linear types is still very young/small, it is very promising!

---

<div class="post-metadata">

**Author:** ![AntC2](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/antc2/32/1872_2.png) [@AntC2](https://discourse.haskell.org/u/AntC2)\
**Post date:** [September 19, 2023, 7:20am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/3 "2023-09-19T07:20:18Z")

</div>

> [@Dato](#):
>
> Well strictly speaking it is not _mutating_ values so my usage of the term MVS is bad

Yes. I see nothing wrong with _using_ a value more than once.

And I’m not sure you’re understanding ‘purity’ in a Haskell context: it means [making the result of a function dependent only on its arguments](https://en.wikipedia.org/wiki/Pure_function). (Not, for example running some IO in the middle of a calculation to grab some value from ‘the world’ – as you can do in `C`.)

The other gotcha Haskell avoids is call-by-reference, where some innocent-looking function can update a global variable (‘Jensen’s Device’ from the ALGOL 60 report nowadays considered harmful). So the result of the function does depend only on the arguments passed; but the value of the rest of the program depends on what evil the function perpetrated in passing.

> [@](#):
>
> not that the idea is new

Well, no. All of the above trickery was commonplace in machine-level programming in the 1950’s. ALGOL was a serious attempt to control/discipline the resulting confusion. ‘Structured Programming’ 1968 went further, leading on to functional programming.

---

<div class="post-metadata">

**Author:** ![Dato](https://avatars.discourse-cdn.com/v4/letter/d/b38774/32.png) [@Dato](https://discourse.haskell.org/u/Dato)\
**Post date:** [September 19, 2023, 8:08am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/4 "2023-09-19T08:08:01Z")

</div>

Thank you. The mutable structure looks nice. (One nit-pick might be why throwing errors instead of returning a `Either` type in the safe version of APIs. 🙂 because we already paid the cost of runtime check already)

If I understand it correctly, by restricting the surface area of my APIs to my dependency (for example, I could decide the only entry of certain library types to be in some restricted files, where I instantly wrap the library type into a linear type, exporting only linear interface), I could be in a fully linear world built upon these wrappers? That is a not bad partial approach to the problem (of resource management).

But again, MVS seems to be a bit richer than just linearity and uniqueness. Other aspects include whether a variable is write-only (which is not in Rust (not built-in at least), but in the passing convention `set` in Hylo, (at least as they (Hylo) claims)), whether some reference(s) is held by others. Maybe Haskell can also (but also has to if want to) add some constructs to allow such feedback to the compiler. The problem though would be that code might be obscured by over-annotation (which Rust kind of already suffers).

Maybe a last side node is that syntax-wise, there is something more intuitive when  
calling `close door` could change the `door`'s type from `OpenedDoor` to `ClosedDoor`. One might instantly argue against this as this complicates reasoning. My thought is that, as long as the compiler work it out, and the behaviour of the called function is well-labled by its type signature, I would prefer this unorthodox solution.

---

<div class="post-metadata">

**Author:** ![Dato](https://avatars.discourse-cdn.com/v4/letter/d/b38774/32.png) [@Dato](https://discourse.haskell.org/u/Dato)\
**Post date:** [September 19, 2023, 8:59am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/5 "2023-09-19T08:59:55Z")

</div>

> I’m not sure you’re understanding ‘purity’ in a Haskell context.

Thank you for correcting my misuse of the term _purity_. I have gone over my head. I should have used the term _immutability_.

> I see nothing wrong with _using_ a value more than once.

For me, it is wrong in Rust because Rust has a finer-grained semantics on the underlying resources and there is no _value_ more than _a value represented at certain computational resources_. Then by default, _using_ is really claiming that from now on nobody but me got to touch it, until I give it away or borrow it to someone else. In contrast, since in Haskell, a _value_ is Just a value agnostic of its underlying representation, it is ok in Haskell to use a value more than once.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [September 19, 2023, 9:55am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/6 "2023-09-19T09:55:41Z")

</div>

> [@Dato](#):
>
> When calling functions on variables, the compiler does things more intelligently and tracks the change of state of the variables being used, instead of being overly optimistic like Haskell where variables are supposed to be unchanged, thus purity has to be enforced, or being overly pessimistic like usual imperative languages where statically analyzing the states is deemed infeasible in general.

Haskell also has this _“hybrid”_ ability (to an extent) - by using the monadic `ST` type, a function can have an imperative implementation but without imposing an imperative interface on its callers, by using `runST`. Others have also mention more recent developments e.g. linear types.

* * *

> [@Dato](#):
>
> But in Haskell, the fundamentals of it seems to prevent such addition?

No. And in fact, your prior observation:

> [@](#):
>
> It is probably better, instead of saying we should ban mutation because it causes all sorts of problems, to say that we should communicate our intention as clearly as possible to the compiler, the caller, and the callee so that when I mutate or want to keep a reference to a value, they can be noticed, so that they can leverage their tools to optimize, verify and modularize.

…is a reasonable description of what usually happens in Haskell: [by using types](https://dl.acm.org/doi/pdf/10.1145/319838.319848), we can indeed _“communicate our intention as clearly as possible to the compiler, the caller, and the callee so that when I mutate or want to keep a reference to a value, they can be noticed, so that they can leverage their tools to optimize, verify and modularize.”_

But this approach just isn’t to everyone’s liking:

- 

> [@](#):
>
> (pages 12-13 of 22)
> 
> _HASKELL_ uses _monads_ for destructive updates and I/O; they add a restricted form of stateful computation to a pure language, retaining referential transparency[\*](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.91.3579&rep=rep1&type=pdf). The disadvantage is that programs become more complicated. Also, if imperative elements of a given application were not taken into account during its design but turn out to be necessary later on, often major parts have to be redesigned or (at least) reimplemented, especially because types change significantly. […]
> 
> The _TRUTH_ team considers this point as one of the biggest drawbacks of the purely functional paradigm as followed by _HASKELL_.
> 
> [Functional programming languages for verification tools: A comparison of Standard ML and Haskell](https://homepages.inf.ed.ac.uk/perdita/haskml.pdf) (2005)

- 

> [@](#):
>
> A straightforward solution would be to stick to the imperative style by using variations of the state monad [[24]](https://www.altocumulus.org/Fudgets/fudgets-fpca93.html#ref-24). This suggests a simple way of using an existing imperative toolkit in a functional program. It is likely, though, that this will imply an imperative programming style throughout the program, so why then use a functional language at all?
> 
> [Fudgets - A Graphical User Interface in a Lazy Functional Language](https://www.altocumulus.org/Fudgets/fudgets-fpca93.html) (1993)

* * *

> [@Dato](#):
>
> […] this feels like a comeback for imperative programming.

…or as I described it [here](http://discourse.haskell.org/t/an-epic-future-for-spj/3573/9):

> […] the siren call of pervasive imperativity is still just as beguiling […]

…a recent case in point:

> [@Disowning an STRef](http://discourse.haskell.org/t/disowning-an-stref/6968):
>
> Had an idle thought this morning: Would it be safe to have a new primitive disownSTRef :: STRef s a -\> ST s (STRef s' a) ? Note that s' is completely unconstrained. In particular, it could be RealWorld, which would mean that you could now create an IORef at toplevel without unsafePerformIO, which would be nice. The idea is that any STRef s a must have been created within the invocation of runST that we’re now in, and so disowning the ref can’t interfere with other state in the outside world. …

Mutation: [it remains just as troublesome](https://www.progsbase.com/blog/global-variables-still-a-major-source-of-problems-in-it-projects), but we still can’t seem to get rid of it entirely! This _seems_ promising:

- 

> [@](#):
>
> (page 46 of 55)
> 
> […] mainstream languages are adopting more and more declarative constructs: comprehensions, iterators, database query expressions, ﬁrst-class functions, and more besides. We expect this trend to continue, driven especially by the goad of parallelism, which punishes unrestricted effects cruelly.

- 

> [@](#):
>
> [LaurentRDC:](http://discourse.haskell.org/t/hasura-migrating-to-rust/6620/18)
> 
> 1. Parallel performance is unmatched, especially given that I put very little effort in it. We’ve been able to tackle problems at a scale we would never have touched before;

…but there doesn’t appear to be a great interest in making Haskell parallel by default (at least for now), which would help _greatly_ to show the advantages of keeping things immutable as much as possible. And so in the absence of progress towards eliminating mutability entirely, new _“not-as-imperative”_ languages have appeared, with each promising to simplify _“the great mutability divide”_ in one form or another…and here we all are.

---

<div class="post-metadata">

**Author:** ![brandonchinn178](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/brandonchinn178/32/5103_2.png) [@brandonchinn178](https://discourse.haskell.org/u/brandonchinn178)\
**Post date:** [September 19, 2023, 2:53pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/7 "2023-09-19T14:53:53Z")

</div>

> [@Dato](#):
>
> Maybe a last side node is that syntax-wise, there is something more intuitive when  
> calling `close door` could change the `door`’s type from `OpenedDoor` to `ClosedDoor`.

This is possible with GADTs!

```haskell
data DoorStatus = Open | Closed

data Door (status :: DoorStatus) where
    OpenDoor :: Door Open
    ClosedDoor :: Door Closed

newDoor :: Door Open
newDoor = OpenDoor

-- This is exhaustive, because the compiler knows
-- OpenDoor is the only constructor that can have
-- the type Door Open
closeDoor :: Door Open -> Door Closed
closeDoor OpenDoor = ClosedDoor

```

IIRC I don’t think Rust could do this

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [September 19, 2023, 4:21pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/8 "2023-09-19T16:21:51Z")

</div>

Yes, but unfortunately the open door is still in scope!

---

<div class="post-metadata">

**Author:** ![brandonchinn178](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/brandonchinn178/32/5103_2.png) [@brandonchinn178](https://discourse.haskell.org/u/brandonchinn178)\
**Post date:** [September 19, 2023, 6:03pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/9 "2023-09-19T18:03:37Z")

</div>

ah I didn’t see the ask was to mutate the type of door… yes that’s quite different.

Possibly some combination of my snippet + linear types + allow name shadowing?

---

<div class="post-metadata">

**Author:** ![HeinrichApfelmus](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/heinrichapfelmus/32/117_2.png) [@HeinrichApfelmus](https://discourse.haskell.org/u/HeinrichApfelmus)\
**Post date:** [September 19, 2023, 6:39pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/10 "2023-09-19T18:39:56Z")

</div>

> [@Dato](#):
>
> But in Haskell, the fundamental of it seems to prevent such addition? I want to know what the Haskell community thinks of these kinds of language features(?)

I remember the 90s, when my computer was running on a PowerPC CPU, and there was this functional language, called [Clean](https://en.wikipedia.org/wiki/Clean_(programming_language)), which was essentially a dialect of Miranda / Haskell, but with some kind of linear types. Instead of writing `:: IO a`, people would write `:: *World → (*World, a)`, a function type where the `World` argument could be used only once.

So, yes, mutability is possible in a Haskell-like language using linear logic.

The real question is: Why would you want to do that? Does it make your code faster to write, easier to prove correct, or faster at running?

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [September 19, 2023, 8:12pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/11 "2023-09-19T20:12:52Z")

</div>

> The real question is: Why would you want to do that? Does it make your code […] easier to prove correct?

Possibly, yes:

> [@](#):
>
> (page 8 of 102)
> 
> In the Haskell proof, the use of the monadic operators (`>>=`, `>>` and `return`) presents a problem. These operators are used to enforce the single threading of the world value by disallowing any other function access of the explicit world value.
> 
> This single threading is a necessary property of any implementation, but when attempting to produce our proofs it is necessary to refer directly to that value and inspect it. This is necessary because the properties that we wish to establish via the proofs are properties of that world value, and it will be necessary to trace the transformations applied to the world in order to verify that the property holds.
> 
> One solution to this problem is to carefully unwrap the monadic value each time the world must be inspected, and re-wrap it again before the next proof step is taken. While possible, this approach requires an inconvenient degree of mechanical work.
> 
> [Proving “make” Correct: I/O Proofs in Two Functional Languages](https://publications.scss.tcd.ie/tech-reports/reports.03/TCD-CS-2003-03.pdf) (2003)

…I only say _“possibly”_ because advances in proof techniques and tool _may_ now have simplified the use of abstract monadic state in correctness proving. But I will defer to the experts here on that topic!

Other work by those and associated authors include:

- [Comparing Proofs about I/O in Three Programming Paradigms](https://publications.scss.tcd.ie/tech-reports/reports.01/TCD-CS-2001-31.pdf) (2001)

- _Proving Correctness of Programs with IO - A Paradigm Comparison_ (2001)

---

<div class="post-metadata">

**Author:** ![HeinrichApfelmus](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/heinrichapfelmus/32/117_2.png) [@HeinrichApfelmus](https://discourse.haskell.org/u/HeinrichApfelmus)\
**Post date:** [October 15, 2023, 6:59pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/12 "2023-10-15T18:59:53Z")

</div>

> [@HeinrichApfelmus](#):
>
> So, yes, mutability is possible in a Haskell-like language using linear logic.
> 
> The real question is: Why would you want to do that? Does it make your code […] easier to prove correct […]?

> [@atravers](#):
>
> Possibly, yes:

What I meant was more “why mutability in the first place” rather than the more specific question of “why linear logic for mutability”. It seems clear to me that a Haskell program which does not mutate explicitly is easier to reason about than a program which does.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [October 15, 2023, 9:09pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/13 "2023-10-15T21:09:35Z")

</div>

> [@HeinrichApfelmus](#):
>
> What I meant was more “why mutability in the first place" […]

From the abstract of [State in Haskell](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.52.3656&rep=rep1&type=pdf) (1995):

- 

> [@](#):
>
> Some algorithms make critical internal use of updatable state, even though their external specification is purely functional.

…with the caveat that some of _those_ algorithms have now been superseded by _“mutability-free”_ alternatives - otherwise, there’s still the type `ST s a`, and most importantly:

`runST :: (forall s . ST s a) -> a`

- 

> [@](#):
>
> The same framework is also used to handle input/output operations […]

…with the caveat that:

> [@](#):
>
> [atravers:](http://discourse.haskell.org/t/what-does-avoid-success-at-all-costs-mean-to-you/5832/2)
> 
> […] this year’s ZuriHac includes invited talks by Conal Elliott and Gabriella Gonzalez - have they finally solved the puzzle of general-purpose denotative **systems** programming?

…oh, that’s right - they didn’t. But they’re not the only ones wanting Haskell to be rid of `IO a`:

[Denotative programming timeline - HaskellWiki](https://wiki.haskell.org/Denotative_programming_timeline)

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/dabrahams/32/3796_2.png) [@dabrahams](https://discourse.haskell.org/u/dabrahams)\
**Post date:** [November 3, 2023, 11:20pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/14 "2023-11-03T23:20:26Z")

</div>

> [@Dato](#):
>
> write-only (which is not in Rust (not built-in at least), but in the passing convention `set` in Hylo, (at least as they (Hylo) claims)),

A slight correction: a `set` parameter in Hylo is not write-only, but must be written before it can be read, because it enters the function in an uninitialized state.

---

<div class="post-metadata">

**Author:** ![dabrahams](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/dabrahams/32/3796_2.png) [@dabrahams](https://discourse.haskell.org/u/dabrahams)\
**Post date:** [November 3, 2023, 11:29pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/15 "2023-11-03T23:29:44Z")

</div>

> [@atravers](#):
>
> [it remains just as troublesome](https://www.progsbase.com/blog/global-variables-still-a-major-source-of-problems-in-it-projects), but we still can’t seem to get rid of it entirely!

The premise of Mutable Value Semantics is that **mutation itself is not troublesome; instead the problem is the mutation of shared state**. Obviously, the global variables mentioned in the article you cite are _extremely_ shared.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [November 4, 2023, 12:29am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/16 "2023-11-04T00:29:55Z")

</div>

But mutation by itself _is_ troublesome:

> [@](#):
>
> By introducing _side effects_ in expressions, the semantics becomes signiﬁcantly more complex. At the same time, several issues arise, related to the _evaluation order_, i.e. the order in which the subparts of an expression are evaluated. If the evaluation order is not strictly deﬁned, the presence of side effects in expressions is a source of non-deterministic behaviour.
> 
> [Denotational Semantics of Evaluation Order in Expressions with Side Effects](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.38.9189&rep=rep1&type=pdf) (1998)

…and mutation is the epitome of side effects! As I mentioned in [this post](http://discourse.haskell.org/t/why-imperative-code-is-worse-than-functional-code/7473/30) on a [related topic](http://discourse.haskell.org/t/why-imperative-code-is-worse-than-functional-code/7473):

> [@](#):
>
> - arbitrary sequencing but no mutation: [confluence.](https://www.cs.cornell.edu/courses/cs4110/2012fa/lectures/lecture14.pdf)
> 
> - arbitrary mutation but no sequencing: nondeterminism!

---

<div class="post-metadata">

**Author:** ![sgraf](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/sgraf/32/392_2.png) [@sgraf](https://discourse.haskell.org/u/sgraf)\
**Post date:** [November 5, 2023, 9:38am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/17 "2023-11-05T09:38:03Z")

</div>

If I were to design a new language, I’d definitely try to have mutable value semantics (in the pure fragment of the language, of course). More recent languages like Lean or Koka do that very successfully. If we had a good macro system, we could just copy the Lean approach, which desugars to simple, pure state passing, just like what the `State` monad would do, but less clumsy. It is the obvious idiom to apply for many kinds of algorithms.

---

<div class="post-metadata">

**Author:** ![atravers](https://avatars.discourse-cdn.com/v4/letter/a/45deac/32.png) [@atravers](https://discourse.haskell.org/u/atravers)\
**Post date:** [November 5, 2023, 11:18am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/18 "2023-11-05T11:18:44Z")

</div>

> […] simple, pure state passing, just like what the `State` monad would do, but less clumsy. It is the obvious idiom to apply for many kinds of algorithms.

> [@atravers](#):
>
> - 
> 
> > [@](#):
> >
> > A straightforward solution would be to stick to the imperative style by using variations of the state monad [[24]](https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.41.9361&rep=rep1&type=pdf). It is likely, though, that this will imply an imperative programming style throughout the program, so why then use a functional language at all?
> > 
> > [Fudgets - A Graphical User Interface in a Lazy Functional Language](https://www.altocumulus.org/Fudgets/fudgets-fpca93.html) (1993)

Sure, the macro system would be dealing with the extra state parameters and arguments…but the code will still look imperative. So either approach isn’t really going to make that much of a difference with regards to aesthetics.

---

<div class="post-metadata">

**Author:** ![avlae](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/avlae/32/3798_2.png) [@avlae](https://discourse.haskell.org/u/avlae)\
**Post date:** [November 5, 2023, 11:55am UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/19 "2023-11-05T11:55:08Z")

</div>

> [@atravers](#):
>
> But mutation by itself _is_ troublesome:

The significant increase in complexity caused by mutation is almost entirely due to sharing.

There is nothing intrinsically more complex about this program compared to its “pure” counterpart:

```haskell
var p = (x: 1, y: 2)
p.x = g(p.y)
p.y = g(p.x)
print(p)

```

Without even mentioning a specific programming language, I strongly suspect that everyone reading this thread knows what the intent of this program is and can predict its outcome. Therefore, renaming each intermediate value of `p` for the sake of immutability would arguably just add noise to this particular program, while collapsing everything into a single expression would make it harder to read. And if `=` offends, one can always pick another symbol.

This program is not only obvious to humans but also to compilers. While smart developers and optimizers can understand that `p' = (x: g(p.y), y: p.y)` is actually equivalent to a partwise in-place update of `p`, it is actually not an easy guess. To the best of my knowledge, a general procedure for all functional updates has yet to be discovered. In contrast, `p.x = g(p.y)` is concise and straightforward.

To me, these observations suggest that there’s an intrinsic value to mutation that is worth preserving and goes beyond convenience. Instead, it relates to some “truth” about the act of computing anything, especially if that computation takes place in the real world. Not everything is better expressed as a declarative relation (O’Neill 2009, [The Genuine Sieve of Erathosthenes](https://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf)); I prefer baking using imperative recipes.

Losing confluence does indeed increases complexity. But again, when sharing off the table, the only issue is to define a precise evaluation order so that people (and machines) can reason about it. That is not as troublesome as it may sound. One can pick innermost, left-to-right and then an expression like `f(p)(g(p.x), g(p.y))` is deterministic and unambiguous.

---

<div class="post-metadata">

**Author:** ![tomjaguarpaw](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/tomjaguarpaw/32/1230_2.png) [@tomjaguarpaw](https://discourse.haskell.org/u/tomjaguarpaw)\
**Post date:** [November 5, 2023, 12:03pm UTC](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619/20 "2023-11-05T12:03:28Z")

</div>

> [@avlae](#):
>
> I strongly suspect that everyone reading this thread knows what the intents of this program is and can predict its outcome.

I don’t think I can understand it! Let me try. First `p.x` is set to `g(p.y)`. Then `p.y` is set to `g` applied to the (presumably) _new_ value of `p.x`, that is `g` of the _original_ `p.y`? So the final value of `p.y` is `g` applied to `g` applied to the original value of `p.y`?

If that’s really the intention then I think I’d prefer to see

```plaintext
p' = (x : g(p.y), y : g(g(p.y)))

```

Isn’t that the “pure counterpart” you’re referring to? I certainly see it as less complex.

[Next page](https://discourse.haskell.org/t/mutable-value-semantics-trend-vs-immutability/7619.md?page=2)
