问题描述
这个问题可以被视为
的后续活动Lift instance of class with a `MonadIO` type-variable to the transformed monad
其中提供了将在何处使用的示例应用程序。
这个想法是一个类型类
class (Monad m) => Class m a where
method :: a -> m ()
存在,并且基本实例位于不同的monad中
instance Class M A where
method = undefined
instance Class (T M) B where
method = undefined
。我想要的是一种将任何实例提升到自身或在变压器堆栈中更高的方式,就像liftIO
对IO
所做的那样。我最初的想法是定义一个提升实例
instance (MonadTrans t,Class m a) => Class (t m) a where
method = lift . method
但是,这存在一个问题,即当应用多个变压器时,会创建重叠的实例,因为lift
是多态的,并且可以用lift . lift
代替。
建议改用类似的默认实例
class (Monad m) => Class m a where
method :: a -> m ()
default method :: (m ~ t n,MonadTrans t,Class n a) => a -> m ()
method = lift . method
然后可以用来声明提升实例
instance (MonadTrans t) => Class (t M) A
instance (MonadTrans t) => Class (t (T M)) B
。这可行,但是需要为每个基本实例声明提升实例,所以我很好奇。还有其他方法可以解决此问题而无需求助于重叠的实例吗?
解决方法
您写
instance (MonadTrans t) => Class (t M) A instance (MonadTrans t) => Class (t (T M)) B
这可行,但是需要为每个基本实例声明提升实例[....]
这不是打算使用这些默认值的方式。实例看起来应该像
instance Class m a => Class (StateT s m) a
instance Class m a => Class (MaybeT m) a
以此类推。