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] |