{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Problem2 where
import Control.Monad (when)
import Control.Concurrent.STM

-- Problem 2a

{- See lecture 10:

pseq, par :: a -> b -> b
-- denotational semantics (pseudo-code):
pseq _|_ y = _|_
pseq _    y = y
par thread main = main

-- Operational semantics (informal):
pseq x y: Evaluate first x, and then y

par thread main: Evaluate thread in parallel, and immediately return main
-}


-- Problem 2b
-- From RWH Ch.28: 
newtype Gold = Gold Int 
  deriving (Eq, Ord, Show, Num)
type Balance = TVar Gold
transfer :: Gold -> Balance -> Balance -> IO ()
transfer qty fromBal toBal = atomically $ do
  fromQty <- readTVar fromBal
  when (qty > fromQty) $
    retry
  writeTVar fromBal (fromQty - qty)
  readTVar toBal >>= writeTVar toBal . (qty +)


-- 1c)
{- Because of referential transparency (purity) the STM code would
evaluate in exactly the same way if run again before any variable has
changed. In that way some unneccessary work can be avoided.

It will continue (redo) the computation after any change of an
accessed variable (so also if the first balance has been decreased,
even though that would still lead to a new retry).
-}