xyz*_*zyz 14 haskell monad-transformers
假设我有简单的newtype声明
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
Run Code Online (Sandbox Code Playgroud)
我想制作MonadBaseControl IO的Foo实例.它应该很简单,因为ReaderT Int IO已经是MonadBaseControl IO的一个实例.但是,使用GeneralizedNewtypeDeriving自动派生它不起作用,因为MonadBaseControl类具有关联类型.
如何为Foo编写MonadBaseControl IO实例?defaultLiftBaseWith和defaultRestoreM应该会有所帮助,但要解密它们的类型有点困难.
use*_*038 17
Foo既不是"基础"单子,也不是单子变换器.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)
Run Code Online (Sandbox Code Playgroud)
该实例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
Run Code Online (Sandbox Code Playgroud)
请注意,如果StM 不是关联的类型系列,您可以执行类似的操作
newtype Foo a = Foo { unFoo :: ReaderT Int IO a }
deriving (Monad, Applicative, Functor, MonadBase IO, MonadBaseControl IO)
type instance StM Foo a = a
Run Code Online (Sandbox Code Playgroud)