module Control.Eff.Lift( Lift (..)
, lift
, runLift
) where
import Control.Eff
import Control.Monad.Base
import Control.Monad.IO.Class (MonadIO (..))
import Data.Typeable
#if MIN_VERSION_base(4,7,0)
#define Typeable1 Typeable
#endif
data Lift m v = forall a. Lift (m a) (a -> v)
#if MIN_VERSION_base(4,7,0)
deriving (Typeable)
#else
instance Typeable1 m => Typeable1 (Lift m) where
typeOf1 _ = mkTyConApp (mkTyCon3 "" "Eff" "Lift")
[typeOf1 (undefined :: m ())]
#endif
instance SetMember Lift (Lift m) (Lift m :> ())
instance Functor (Lift m) where
fmap f (Lift m k) = Lift m (f . k)
instance (Typeable1 m, MonadIO m, SetMember Lift (Lift m) r) => MonadIO (Eff r) where
liftIO = lift . liftIO
instance (MonadBase b m, Typeable1 m, SetMember Lift (Lift m) r) => MonadBase b (Eff r) where
liftBase = lift . liftBase
lift :: (Typeable1 m, SetMember Lift (Lift m) r) => m a -> Eff r a
lift m = send (inj . Lift m)
runLift :: (Monad m, Typeable1 m) => Eff (Lift m :> ()) w -> m w
runLift m = loop (admin m) where
loop (Val x) = return x
loop (E u) = prjForce u $ \(Lift m' k) -> m' >>= loop . k