Suppose I have simple newtype declaration
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
I want to make Foo instance of MonadBaseControl IO. It should be easy, since ReaderT Int IO is already an instance of MonadBaseControl IO. However, automatically deriving it using GeneralizedNewtypeDeriving doesn't work, because MonadBaseControl class has an associated type.
How can one write a MonadBaseControl IO instance for Foo? defaultLiftBaseWith and defaultRestoreM should be helpful, but it's a bit hard to decipher their types.
Foo
is neither a "base" monad, nor a monad transformer. defaultLiftBaseWith
won't be helpful here, since you want the instance for Foo
to be identical to the one for ReaderT Int IO
.
First, use GND to get the boring instances:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Trans.Control
import Control.Monad.Base
import Control.Monad.Reader
import Control.Applicative
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
deriving (Monad, Applicative, Functor, MonadBase IO)
The instance for MonadBaseControl IO
just removes the newtype, uses the functions from the ReaderT
instance, and puts the result back in the newtype:
instance MonadBaseControl IO Foo where
type StM Foo a = a
liftBaseWith f = Foo $ liftBaseWith $ \q -> f (q . unFoo)
restoreM = Foo . restoreM
Note that if StM
wasn't an associated type family, you could do something like
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
deriving (Monad, Applicative, Functor, MonadBase IO, MonadBaseControl IO)
type instance StM Foo a = a
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With