Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to define MonadShControl for a newtype? #212

Open
doyougnu opened this issue Dec 21, 2021 · 0 comments
Open

How to define MonadShControl for a newtype? #212

doyougnu opened this issue Dec 21, 2021 · 0 comments

Comments

@doyougnu
Copy link

Shelly.Lifted is a great idea, however I don't really know how to use it and there is a lack of documentation (related: #135 from 5 years ago! Also ben's comment: #115 (comment)) . My use case is simply a ReaderT over Sh rather than IO. This leads me to something like:

-- | our script monad, just a reader of IO in the guise of Shelly
newtype ScriptMT r m a = ScriptMT { unScriptMT :: ReaderT r m a }
  deriving newtype ( Functor, Applicative, Monad
                   , MonadIO, MonadReader r, MonadTrans, MonadTransControl
                   , MonadSh
                   )

and then we derive MonadBase and MonadBaseControl:

type ScriptM r = ScriptMT r Sh.Sh

deriving instance MonadBase        IO (ScriptM r)
deriving instance MonadBaseControl IO (ScriptM r)

and this is great! We get exception handling functions like try from Control.Exception.Lifted, and we can easily use lots of functions in Shelly.Lifted since we derive a MonadSh instance.

But how do I use functions with a MonadShControl constraint? There are a decent number of these functions that are useful, most notable escaping.

If I try to define it by hand I end up with something like:

instance MonadShControl m =>  MonadShControl (ScriptMT r m) where
  data ShM (ScriptMT r m) a = ScriptMTShM (m a)
  liftShWith f = ScriptMT $ \r ->
    liftM id $ liftShWith $ \runInSh -> f $ \k ->
    liftM ScriptMTShM $ runInSh $ unScriptMt r k

but this cannot unify the ReaderT. Normally I would think that liftShWith would have to be a dead simple instance of unlifting and calling liftShWith for ReaderT. So all I need to do is unwrap ScriptMT, run the function passed to liftShWith and then re-wrap with the associated type family. But none of that works and so I'm at a loss and am forced to use a type synonym rather than a newtype.

Perhaps there is just missing documentation around this type class showing how to define an instance for a monad transformer? Or perhaps this is just a problem with my definition because I pinned the ReaderT in my newtype.

Thanks for Shelly, any help appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant