Search code examples
purescript

Mutating state in Purescript


I am just starting to learn Purescript so I hope that this is not a stupid question.

Suppose that we have an object

a = {x:1,y:2}

an we want to change x to equal 2. As far as I can see if we use the ST monad we will have to copy the whole object in order to change the value. If the initial object is big this would be very inefficient. What is the right way to mutate objects in place?


Solution

  • The ST monad is a fine approach, but depending on your use case, there may or may not be standard library functions for this.

    The Data.StrMap module in purescript-maps defines a foreign type for homogeneous records with string keys, so if your values all have the same type, you could use Data.StrMap.ST to mutate your record in place.

    If not, you should be easily able to define a function to update a record in place using ST and the FFI. The tricky bit is picking the right type. If you want to do something for a specific key, you could write a function

    setFoo :: forall r a h eff. STRef h { foo :: a | r } -> a -> Eff (st :: ST h | eff) Unit
    

    for example. Defining a generic setter would be more difficult without losing type safety. This is the trade-off made by Data.StrMap: you restrict yourself to a single value type, but get to use arbitrary keys.