
2. How do you implement a program that is fundamentally about state mutation in a programming language which abhors state mutation?
Its not clear games are fundamentally about mutation, anymore than, say, window managers are. State we do with monads.
Indeed. Ignoring the concept of a monad for the moment, you could think of your tetris engine as a function mapping a stream of user inputs to a stream of resulting states. ie data Action = None | Rotate | Left | Right | Down data State = ... tetris :: [Action] -> [State] tetris = scanl step step :: State -> Action -> State step = ... where State would probably model the playing grid and where all the squares are, including the current position of the falling piece. Remember that scanl has signature equivalent to scanl :: (s -> a -> s) -> s -> [a] -> [s] Given some function f on states, an (infinite) list of actions and an initial state, it will return an (infinite) list of states determined by f and the list of actions. The list of inputs from the user can be gotten using the 'getContents' function, for instance. The 'tetris' function will yield new states only as new inputs from the user are available; that's the magic of lazyness. So you could then take this list of states and display each to the user, as they become available. Your 'main' function would look something like: main = do s <- getContents lets actions = parseActions s mapM_ drawTetrisGrid (tetris actions) where drawTetrisGrid renders a state to the screen: drawTetrisGrid :: State -> IO () Some people think getContents is evil, for reasons I won't go into, in which case another solution would probably involve a monad looking like StateT IO, as Dons suggests. Either way, it really isn't a problem to implement tetris in a functional style, and Haskell is certainly up to the task! Hope this helps, Mathieu