{-# language DeriveAnyClass #-}
{-# language DataKinds #-}
{-# language FlexibleContexts #-}
{-# language GADTs #-}
{-# language RankNTypes #-}
{-# language PolyKinds #-}
{-# language UndecidableInstances #-}

module IO.Effects.Lift where

import IO.Effects.Internal ( Member, Program( Program, programToIO ), ProgramWithHandler, interpret, send )
import Control.Monad.IO.Class ( MonadIO, liftIO )


data Lift n m a where
  Lift :: n a -> Lift n m a


-- | Escape the 'Program' monad when you are using 'Lift IO'.
{-# inline run #-}
run :: ProgramWithHandler ( Lift IO ) '[] a -> IO a
run p =
  programToIO ( interpret ( \( Lift io ) -> Program io ) p)


instance Member ( Lift IO ) es => MonadIO ( Program es ) where
  {-# inline liftIO #-}
  liftIO =
    send . Lift