packages feed

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 }