Saurabh Nanda
Saurabh Nanda

Reputation: 6793

How to create a monad which allows IO but is NOT a MonadIO?

I'm trying to create a monad where only specific IO functions are allowed. This means that this hypothetical monad cannot be a MonadIO and cannot allow liftIO to be called.

Here's what I have till now, but I'm stuck with the Monad instance for AppM:

data AppM a = AppM {unwrapAppM :: ReaderT Env (LoggingT IO) a}

instance Functor AppM where
  fmap fn appm = AppM $ fmap fn (unwrapAppM appm)


instance Applicative AppM where
  pure a = AppM $ pure a

Upvotes: 3

Views: 240

Answers (1)

epsilonhalbe
epsilonhalbe

Reputation: 15959

If you just want to hide the MonadIO-ness of your AppM

I would go on and put in a

{-# LANGUAGE GeneralizedNewtypeDeriving #-}

and change the data declaration to

newtype App a = App {runApp :: ReaderT Env (LoggingT IO) a}
              deriving (Functor, Applicative, Monad, MonadReader Env,
                       , MonadLoggerIO }

Thus your App is no MonadIO if you need to liftIO like actions you can provide those inside of your library like

putStrLn :: String -> App ()
putStrLn = fmap App . liftIO Prelude.putStrLn

Note: the liftIO is for ReaderT Env (LoggingT IO) () which then is wrapped into App, and you do not expose full IO capabilities.

Update

Regarding the question how to implement Functor, Applicative and Monad it is just the mere task of wrapping/unwrapping:

instance Functor App where
   fmap f = App . fmap f . runApp

instance Applicative App where
  pure = App . pure
  mf <*> mx = App (runApp mf <*> runApp mx)

instance Monad App where
  mx >>= f = App $ (runApp mx) >>= (runApp . f)

the last line is the only tricky one - as

>>= :: ReaderT Env (LoggingT IO) a -> (a -> ReaderT Env (LoggingT IO) b) -> ReaderT Env (LoggingT IO) b

but mx :: App a and f :: a -> App b so we need

runApp :: App a -> ReaderT Env (LoggingT IO) a

to unwrap the result type of f to work in the unwrapped setting - which seems really obvious when written down, but can cause some headache, before that.

Update2

I found that paper someone linked me a long long time a go (but in the same galaxy) from the monad reader Ed Z. Yang - Three Monads (Logic, Prompt, Failure)

Upvotes: 9

Related Questions