我目前正在Haskell学习使用Monad-Transformers。我使用StateT和ExceptT组成了一个简单的单台转换器。
type DatabaseT m = StateT DatabaseState (ExceptT DatabaseError m)已经有一些与DatabaseT一起工作的函数,如:
connectDB :: MonadIO m => DBMode -> DatabaseT m ()
isConnected :: Monad m => DatabaseT m Bool为了使这些函数的提升更容易,我想定义一个类似于MonadIO的类型类。
class Monad m => MonadDB m where
liftDB :: Monad m' => DatabaseT m' a -> m a现在,有问题的部分是将DatabaseT m作为一个实例(如果是MonadDB )。查看implementation of MonadIO,这个函数应该是标识函数:
instance Monad m => MonadDB (DatabaseT m) where
liftDB = id但是,这段代码没有编译:
Couldn't match type ‘m'’ with ‘m’
‘m'’ is a rigid type variable bound by
the type signature for:
liftDB :: forall (m' :: * -> *) a.
Monad m' =>
DatabaseT m' a -> DatabaseT m a
‘m’ is a rigid type variable bound by
the instance declaration
Expected type: DatabaseT m' a -> DatabaseT m a
Actual type: DatabaseT m a -> DatabaseT m a
In the expression: id
In an equation for ‘liftDB’: liftDB = id
In the instance declaration for ‘MonadDB (DatabaseT m)’
Relevant bindings include
liftDB :: DatabaseT m' a -> DatabaseT m a似乎有一个Monad MyMonad的Monad变压器类型类,具有类似于liftMyMonad的函数,当MyMonad本身是Monad-转换器时,它就不能工作了。
这是一种使DatabaseT m操作的提升更通用的有效方法,还是根本上存在缺陷?
如果是这样的话,我如何从DatabaseT m堆栈的任何位置提升DatabaseT操作?
发布于 2021-10-11 22:38:35
你想要的结束状态可能不是你想要的结束状态。也就是说,对于大多数需求来说,这并不是很好:
class Monad m => MonadDB m where
liftDB :: Monad m' => DatabaseT m' a -> m a典型的解决方案是根本不编写这样的实例,而是编写:
class Monad m => MonadDB m where
connectDB :: DBMode -> m ()
isConnected :: m Bool这使你能够:
lift。https://stackoverflow.com/questions/69532999
复制相似问题