---------------------------------------------------------------------------
-- |
-- module      :  Control.Monad.Trans.Cont
-- Copyright   :  (c) Evgeniy Permyakov 2010
-- License     :  BSD-style (see the LICENSE file in the distribution)
--
-- Maintainer  :  permeakra@gmail.com
-- Stability   :  experimental 
-- Portability :  portable (haskell - 2010)
-- Actually, this module is redundant, because Coroutines provides superset of this functional. 
-- However, it is simplier to use, so it is provided.
module Control.Monad.Trans.Invoke where
import Control.Monad.Trans.Class
import Control.Monad.IO.Class

newtype InvokeT p m a = InvokeT ( (p -> m () ) -> m a  )

invokeT :: ( (p -> m () ) -> m a ) -> InvokeT p m a
invokeT = InvokeT

runInvokeT :: InvokeT p m a -> ( p -> m () ) -> m a
runInvokeT (InvokeT a) f = a f

instance Functor m => Functor (InvokeT p m) where
 fmap f m = invokeT $ \i -> fmap f (runInvokeT m i)

instance Monad m => Monad (InvokeT p m) where 
 return a = invokeT $ \_ -> return a
 m >>= k  = invokeT $ \f -> runInvokeT m f >>= \x -> runInvokeT (k x) f

invoke :: p -> InvokeT p m ()
invoke p = invokeT $ \f -> f p 



