barrie-0.4.1: demos/CalcState.hs
module CalcState (CalcState, startState,
calcValue, addDigit, op, eval, clear,
calcBase, setBase)
where
-- This is the state of the calculator: the current value, the current
-- partial function, and a flag to tell us whether the next digit will
-- start a new number (actually, the sense is reversed from that, but you
-- get the idea)
data CalcState = CS { calcValue :: Int,
calcOp :: Int -> Int,
startNew :: Bool,
calcBase :: Int
}
startState :: CalcState
startState = CS 0 id False 10
-- Add a single digit to the state. Depending on the boolean value,
-- this could be the start of a new number, or the new rightmost digit
-- of the existing number
addDigit :: Int -> CalcState -> CalcState
addDigit n (CS r f True base) = CS n f False base
addDigit n (CS r f False base) = CS (r * base + n) f False base
-- Apply an operation to the calculator. In fact, this partially applies
-- the operation to what's already there. The current partial operation
-- is applied to the current number.
op :: (Int -> Int -> Int) -> CalcState -> CalcState
op f (CS r g _ base) = CS (g r) (f (g r)) True base
-- Evaluate the state. That is, apply the current partial operation to
-- the current number, resetting everything else
eval :: CalcState -> CalcState
eval (CS r f _ base) = CS (f r) id True base
-- Clear the state.
clear :: CalcState -> CalcState
clear = const startState
setBase :: Int -> CalcState -> CalcState
setBase newBase cs = cs { calcBase = newBase }