My program has a client and a server component that need to exchange data. Each of them has a state in which they mutate. The mutation is performed explicitly as follows:
There attitude
class Diff ab where commit :: a -> b -> a
This suggests that type b can be considered a "piece" of type a and that you can modify objects of type a by "commuting" an object of type b .
So, you change the state, these pieces are registered and transferred to the client, who also has an instance of the above relationship, only for another type a .
Now, here's the deal. My server status is a record with many fields. All of them can change, because you know this state. This is what he does. This forces me to write a separate case in my "chunk" type for each possible field so that I can send them over the network. It would be great if I somehow passed any function state -> state , but I do not see this. The client shares the server code, so he knows about the structure of my "pieces", and the part in which she must interpret them in order to update it, the local state is what I can manage.
What was interesting to me was if I could use the lens here to automate the generation of update pieces. My whole “piece” of type, after all, is a clumsy setter with a common structure that I can serialize.
What would be the best way to avoid code repetition here?
To better understand what my code looks like, here is an example of how the server state is looking for a pong game.
data State = State { playerPaddle :: Double , aiPaddle :: Double , ball :: Vec2 Double , ballV :: Vec2 Double } deriving Show data Update = BallPos (Vec2 Double) | BallVel (Vec2 Double) | PlayerPos Double | AIPos Double instance Diff State Update where commit s (BallPos p) = s { ball = p } commit s (BallVel p) = s { ballV = p } commit s (PlayerPos p) = s { playerPaddle = p } commit s (AIPos p) = s { aiPaddle = p }