module ContM (HasCont(..), runCont, ContM) where

import MT


import Monad


newtype ContM o i = C { ($$) :: (i -> o) -> o }

runCont :: ContM i i -> i
runCont m       = m $$ id


instance Monad (ContM o) where
  return x    = C (\k -> k x)
  C m >>= f   = C (\k -> m (\i -> f i $$ k))
  C m >> C n  = C (m . const . n)

instance HasBaseMonad (ContM o) (ContM o) where
  inBase        = id


instance HasCont (ContM o) where
  callcc f    = C (\k -> f (\a -> C (\d -> k a)) $$ k)



shift           :: ((a -> ContM b b) -> ContM b b) -> ContM b a
shift f         = C (\k -> runCont $ f (\a -> C (\k' -> k' (k a))))

reset           :: ContM a a -> ContM a a
reset m         = return (runCont m)


{-
test1           = do x <- reset $ do y <- shift (\f -> do z <- f "100"
                                                          f z)
                                     return ("10 + " ++ y)
                     return $ "1 + " ++ x


test2           = liftM ("1 + " ++) $ reset $ liftM ("10 + " ++) $ shift (\f -> return "100")
test3           = liftM ("1 + " ++) $ reset $ liftM ("10 + " ++)  $ shift $ \f -> liftM2 (\x y -> x ++ " + " ++ y) (f "100") (f "1000")
-}

