module ContMT (HasCont(..), MT(..), at, Z, S, removeCont, runCont, WithCont) where import MT import Monad(liftM,MonadPlus(..)) import Control_Monad_Fix import ImpUtils newtype WithCont o m i = C { ($$) :: (i -> m o) -> m o } removeCont :: WithCont o m i -> (i -> m o) -> m o removeCont = ($$) runCont :: Monad m => WithCont i m i -> m i runCont k = k $$ return -------------------------------------------------------------------------------- instance Monad m => Functor (WithCont o m) where fmap = liftM instance Monad m => Monad (WithCont o m) where return x = C ($ x) C m >>= f = C $ \k -> m $ \a -> f a $$ k instance MT (WithCont o) where lift m = C (m >>=) instance MonadPlus m => MonadPlus (WithCont o m) where mzero = lift mzero C m1 `mplus` C m2 = C $ \k -> m1 k `mplus` m2 k -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- instance HasEnv m ix e => HasEnv (WithCont o m) ix e where getEnv ix = lift (getEnv ix) inModEnv ix f (C m) = C (inModEnv ix f . m) instance HasState m ix s => HasState (WithCont o m) ix s where updSt ix = lift . updSt ix instance HasOutput m ix o => HasOutput (WithCont ans m) ix o where outputTree ix = lift . outputTree ix instance HasExcept m x => HasExcept (WithCont o m) x where raise = lift . raise handle f m = C $ \k -> handle (\x -> f x $$ k) (m $$ k) instance Monad m => HasCont (WithCont o m) where callcc f = C $ \k -> f (\a -> C $ \d -> k a) $$ k -------------------------------------------------------------------------------- instance HasBaseMonad m n => HasBaseMonad (WithCont o m) n where inBase = lift . inBase instance HasRefs m r => HasRefs (WithCont () m) r where newRef = lift . newRef readRef = lift . readRef writeRef r = lift . writeRef r -- Magnus' fixpoint implementation instance (MonadFix m, HasRefs m r) => MonadFix (WithCont () m) where mfix m = C $ \k -> do x <- newRef Nothing let xcases j n = readRef x >>= maybe n j k' b' = xcases (const (k b')) (writeRef x (Just b')) mfix $ \b -> do m b $$ k' xcases return (return (error "mfix in ContMT is bottom")) xcases k (return ()) shift :: Monad m => ((a -> WithCont o m o) -> WithCont o m o) -> WithCont o m a shift f = C (\k -> runCont $ f (\a -> C (\k' -> k' =<< k a))) reset :: Monad m => WithCont o m o -> WithCont o m o reset m = C (\k -> k =<< runCont m) test1 :: WithCont String IO String test1 = do x <- reset $ do y <- shift (\f -> do z <- f "100" f z) return ("10 + " ++ y) inBase (print "hello") 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") -}