creating MonadBaseControl instance for newtype

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 
链接地址: http://www.djcxy.com/p/43458.html

上一篇: 我是否可以将这种新类型实现为其他类型的组合?

下一篇: 为newtype创建MonadBaseControl实例