Skip to content

Instantly share code, notes, and snippets.

it "deposits money" $ do
  runIdentity (execStateT (deposit 100) newBank) `shouldBe` [Deposit 100]
it "withdraws money" $ do
  runIdentity (execStateT (withdraw 100) newBank) `shouldBe` [Withdrawal 100]
instance MonadStatementPrinter (Writer String) where
  printStmt = tell
instance MonadStatementPrinter IO where
  printStmt = putStr
printStatement :: (Monad m, MonadStatementPrinter m) => StateT [Transaction] m ()
printStatement = do
  transactions <- get
  let statement = generateStatement transactions
  lift $ printStmt statement
class MonadStatementPrinter m where
  printStmt :: String -> m ()
areTheseEqual :: a -> a -> Bool
areTheseEqual a b = a == b
testPrintStatement :: StateT [Transaction] (Writer String) ()
testPrintStatement = innerPrintStatement (\statement -> tell statement)
it "prints a statement" $ do
  -- evalStateT works just like evalState, except it will return us a `Writer String ()` instead of just `()`
  -- we can then use execWriter to get the String from Writer String ()
  execWriter (evalStateT testPrintStatement [Deposit 100, Withdrawal 50]) `shouldBe` "Deposited 100\nWithdrew 50"
printStatement :: StateT [Transaction] IO ()
printStatement = innerPrintStatement putStr
innerPrintStatement :: Monad m => (String -> m ()) -> StateT [Transaction] m ()
innerPrintStatement printer = do
  transactions <- get
  let statement = generateStatement transactions
  lift (printer statement)
it "sends statement to the aether" $ do
  runStateT printStatement [Deposit 100] `shouldBe` … -- the return type is IO ((), [Transaction]), statement is gone
main = do
  runStateT useMyBank []
  pure () - we need to return IO () for main
useMyBank :: StateT [Transaction] IO ()
useMyBank = do
  deposit 200
  withdraw 100
  printStatement