{-# LANGUAGE CPP, ScopedTypeVariables #-}

-- If we instead commute the monad transformers we can change the
-- reader value observed by a continuation.

import Control.Monad.Cont as C
import qualified Control.Monad.Reader as R
import Data.IORef
import Text.Printf

type M a = C.ContT () (R.ReaderT Int IO) a

test ref = do 
  x <- R.ask 
  liftIO$ printf "Observed value %d before callCC\n" x 
  callCC$ \cont -> do
     liftIO$ writeIORef ref cont
     liftIO$ printf "Write ioref inside callcc...\n" 
  z <- R.ask 
  liftIO$ printf "Observed value %d in invoked continuation\n" z
  return ()

main = do ref :: IORef (() -> M ()) <- newIORef (error "should not be used")
          let m0 = test ref
	      m1 = C.runContT m0 (\ () -> return ())
	      m2 = R.runReaderT m1 (100::Int)
          m2 

          k <- readIORef ref
          let m3 = do 
		      w <- lift$ R.ask 
		      liftIO$ putStrLn ("In new runReader instance: observed " ++ show w)
		      k ()
		      liftIO$ putStrLn  " !! Should not reach here..."

	  R.runReaderT (C.runContT m3 (\ () -> return ())) 200
          putStrLn "Done with main."