I'm currently designing a numerical algorithm which as part of its operations requires updating a vector of doubles many times. Due to the fact that the algorithm has to be as space and time efficient as possible, I do not want to code the traditional type of FP code which creates many versions of the data structure under the hood after each operation on it. Neither do I want to create mutable data structures and have them globally available. Consequently, I have decided to use a mutable data structure but then choose to do the the mutable operations in a State monad. Since this is my first stab at using a State monad, I want to confirm the whether I have or have not
- preserved referential transparency
- maintained functional purity
The update function transitions the data structure state. Since the destructive update is localised within this function and a handle to the data structure cannot be got at from outside, I think this function is pure and referentially transparent.
def update(i : Int,d : Double) = State[ArraySeq[Double], Unit]{
case xs: ArraySeq[Double] => {xs(i) = d; (xs, ())}
}
The app function is a toy function which will consume a sequence of doubles and modify it's state:
def app : State[ArraySeq[Double], Unit] = for{
_ <- update(0, 3.142)
// do a heap of stuff on ArraySeq
}yield()
Call:
app(Vector(0.0, 1.0, 2.0, 3.0, 4.0).to[ArraySeq])._1.to[Vector]
Result:
res0: Vector[Double] = Vector(3.142, 1.0, 2.0, 3.0, 4.0)