{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module Control.Effect.IO (UIO, runUIO, syncIO, EffUIO(..), runExceptionalIO) where
import Control.Effect
import Control.Exception (SomeException, throwIO, try)
import Control.Monad ((>=>))
import Control.Monad.Trans.Class (lift)
import qualified Control.Effect.Exception as Ex
-- | Lift an 'IO' action and explictly throw an synchronous IO exceptions that
-- occur.
syncIO :: (Interprets (Either SomeException) m,EffUIO m)
=> IO a -> m a
syncIO io = liftUIO (UIO (try io)) >>= interpret -- TODO This is catching async
runExceptionalIO
:: Eff (Either SomeException) IO a -> IO a
runExceptionalIO = Ex.try >=> either throwIO return
newtype UIO a =
UIO {runUIO :: IO a}
deriving (Functor,Applicative,Monad)
class Monad m => EffUIO m where
liftUIO :: UIO a -> m a
instance EffUIO IO where
liftUIO (UIO io) = io
instance EffUIO UIO where
liftUIO = id
instance EffUIO m => EffUIO (Eff r m) where
liftUIO = lift . liftUIO