What is the best way to represent state updated by input?
I simulate physical system. It has state (coordinates, velocities). State is updated by simulation that takes some parameters (forces) from stdin. Result goes to stdout after each simulation cycle.
Program should stop after N cycles.
I've done it with readIORef and writeIORef but this is ugly.
One simple way to do this would be brachiating along a lazy (possibly infinite) list instead of doing any explicit IO.
import Control.Monad.State
-- Prerequisites:
data SimState -- coordinates & velocities.
data SimTVParams -- what's read from input. `instance Read`.
initialState :: SimState
simStep :: SimTVParams -> SimState -> SimState
simStateInfo :: SimState -> String
-- How to do the simulation:
main :: IO ()
main = interact $
unlines . map simStateInfo
. simulate initialState
. map read . lines
simulate :: SimState -> [SimTVParams] -> [SimState]
simulate iState = (`evalState` iState) . mapM (state . step)
where step params oldState = (newState, newState)
where newState = simStep params oldState
You an write this at a very high-level using pipes. First, I will assume that you have already defined the following types, values, and functions:
data Status = Status deriving (Show)
data Param = Param deriving (Read)
initialState :: Status
initialState = undefined
update :: Status -> Param -> Status
update = undefined
numCycles :: Int
numCycles = undefined
Now here comes the pipes code:
import Pipes
import qualified Pipes.Prelude as P
main = runEffect $
P.readLn >-> P.take numCycles >-> P.scan update initialState id >-> P.print
You can read this as a data processing pipeline from left to right:
P.readLn reads input parameters from standard input. It will halt if you reach end of inputP.take numCycles only allows up to numCycles parameters to pass throughP.scan runs your simulation using the provided initial state and update function and then streams each intermediate state further downstreamP.print prints out each intermediate stateTo learn more about the pipes library, you can read the official pipes tutorial.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With