I\'m currently writing a Haskell program that involves simulating an abstract machine, which has internal state, takes input and gives output. I know how to implement this u
One option is to make your state transformations into pure functions operating on Machine
values:
getValue :: Machine -> Int
getValue (Register x) = x
addToState :: Int -> Machine -> Machine
addToState i (Register x) = Register (x + i)
Then you can lift them into State
as needed, writing State
actions on multiple machines like so:
doInteraction :: State (Machine, Machine) Int
doInteraction = do
a <- gets $ getValue . fst
modify $ first $ addToState (-a)
modify $ second $ addToState a
gets $ getValue . snd
Where first
(resp. second
) is a function from Control.Arrow
, used here with the type:
(a -> b) -> (a, c) -> (b, c)
That is, it modifies the first element of a tuple.
Then runState doInteraction (Register 3, Register 5)
produces (8, (Register 0, Register 8))
as expected.
(In general I think you could do this sort of “zooming in” on subvalues with lenses, but I’m not really familiar enough to offer an example.)