Implement a bank account that can deposit, withdraw and print a statement to the console.
Follow the Tell, don't ask principle. All methods should be void.
void Deposit(int)
void Withdraw(int)
void PrintStatement()
Develop an API that moves a Mars Rover around on a grid.
| -- we'll need an instance of `Writer String` for `MonadCurrentDateTime` for our test | |
| instance MonadCurrentDateTime (Writer String) where | |
| currentDateTime = pure firstOfJan2019 | |
| testMyBank :: StateT [Transaction] (Writer String) () | |
| testMyBank = do | |
| deposit 200 | |
| withdraw 100 | |
| deposit 3000 | |
| printStatement |
| deposit amount = do | |
| now <- lift currentDateTime | |
| modify $ \transactions -> transactions ++ [Deposit amount now] |
| instance MonadCurrentDateTime IO where | |
| currentDateTime = getCurrentTime -- this comes from Data.Time | |
| -- in our test file | |
| instance MonadCurrentDateTime Identity where | |
| currentDateTime = pure firstOfJan2019 |
| deposit :: (Monad m, MonadCurrentDateTime m) => Int -> StateT [Transaction] m () | |
| withdraw :: (Monad m, MonadCurrentDateTime m) => Int -> StateT [Transaction] m () |
| class MonadCurrentDateTime m where | |
| currentDateTime :: m UTCTime |
| firstOfJan2019 = UTCTime (fromGregorian 2019 01 01) (secondsToDiffTime 0) | |
| -- ... | |
| deposit amount = modify $ \transactions -> transactions ++ [Deposit amount firstOfJan2019] | |
| -- same for `withdraw`, and in test functions |
| import Data.Time | |
| data Transaction = Deposit Int UTCTime | Withdrawal Int UTCTime |
| -- our Transaction type | |
| data Transaction = Deposit Int | Withdrawal Int | |
| -- our bank functions | |
| deposit :: Monad m => Int -> StateT [Transaction] m () | |
| deposit amount = modify $ \transactions -> transactions ++ [Deposit amount] | |
| withdraw :: Monad m => Int -> StateT [Transaction] m () | |
| withdraw amount = modify $ \transactions -> transactions ++ [Withdrawal amount] |