假设我有简单的newtype声明
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
我想制作MonadBaseControl IO的Foo实例。它应该很简单,因为ReaderT Int IO已经是MonadBaseControl IO的一个实例。但是,使用GeneralizedNewtypeDeriving自动导出它并不起作用,因为MonadBaseControl类具有关联的类型。
如何为Foo编写MonadBaseControl IO实例? defaultLiftBaseWith和defaultRestoreM应该会有所帮助,但要破译它们的类型有点难。
答案 0 :(得分:17)
Foo
既不是"基地" monad,也不是monad变压器。 defaultLiftBaseWith
在这里没有帮助,因为您希望Foo
的实例与ReaderT Int IO
的实例相同。
首先,使用GND来获取无聊的实例:
{-# 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)
MonadBaseControl IO
的实例只删除newtype,使用ReaderT
实例中的函数,并将结果放回newtype中:
instance MonadBaseControl IO Foo where
type StM Foo a = a
liftBaseWith f = Foo $ liftBaseWith $ \q -> f (q . unFoo)
restoreM = Foo . restoreM
请注意,如果StM
不是关联的类型系列,您可以执行类似
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
deriving (Monad, Applicative, Functor, MonadBase IO, MonadBaseControl IO)
type instance StM Foo a = a