In-place update in IO

Is there a (low-level) GHC feature which will allow an in-place update of a particular constructor/record field in an IORef, for efficiency?

Given the following code:

data Object = Object {
    field1 :: Int
    field2 :: VeryLargeDataType
    }

main :: IO ()
main = do
    var <- newIORef
    writeIORef var $ Object {
             field1 = 42,
             field2 = lotsOfData
        }
    modifyIORef var (\a -> a { field1 = (field1 a + 1) } )
    ...

GHC will read out the very large object, perform the trivial modification, and write it back.

In theory, an in-place update of just the field would be sufficient, and far more efficient.

Is there any GHC feature, e.g. a low-level primitive, that would allow me to do this for any ADT?

I know the special-case solution is to make ther fields IORefs rather than the structure, but I’m looking for a way to do this with any structure, including from a library.

It sounds like you want the mutable constructor fields proposal. This would introduce precisely what you want. At this point it is merely looking for an implementor (although I believe Iavor Diatchki and Ryan Yates both have (stalled?) work-in-progress implementations).

I was surprised to find that the mutable constructor fields proposal didn’t have an implementation tracking ticket. I have opened GHC #19387 to fill this role and pinged both Iavor and Ryan. Hopefully they will pop up soon.

Mutable fields are very cool!

But in this case is there anything to worry about? field2 will be a pointer to the very large thing so updating the other field will still be cheap.

True. I simplified slightly. It matters more when Object has a large number of fields (broad, rather than deep.)

I’m understanding MutableFields still requires fields to be declared mutable but not a way of ‘lifting’ a pure type into mutable. (Although you could probablyy enable it with some generic code).

Is there a conceptual problem with this idea?

Mutating an otherwise immutable datatype would be bad unless you have some kind of single-use guarantees (linearity).

Which would let the compiler ‘know’ its inside an IORef.

So we need to wait for a union of MutableFields and broader adoption of LinearTypes.