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 input
P.take numCycles only allows up to numCycles parameters to pass through
P.scan runs your simulation using the provided initial state and update function and then streams each intermediate state further downstream
P.print prints out each intermediate state
To learn more about the pipes library, you can read the official pipes tutorial.