Haskell 有没有一种方法可以在不重叠实例的情况下,使用monad类型变量以多态方式提升类的实例?

Haskell 有没有一种方法可以在不重叠实例的情况下,使用monad类型变量以多态方式提升类的实例?,haskell,typeclass,monad-transformers,overlapping-instances,Haskell,Typeclass,Monad Transformers,Overlapping Instances,这一问题可以被视为是一个后续问题 它提供了一个应用程序示例,说明了将在何处使用它 这个想法是一个typeclass 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 。我想要的是一

这一问题可以被视为是一个后续问题

它提供了一个应用程序示例,说明了将在何处使用它

这个想法是一个typeclass

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替换。提升

建议使用类似的默认实例

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(tm)A
实例(MonadTrans t)=>Class(t(tm))B
这是可行的,但需要为每个基础实例声明提升实例[…]

这并不是那些默认设置的用途。实例应该如下所示

instance Class m a => Class (StateT s m) a
instance Class m a => Class (MaybeT m) a
等等。

你写

instance(MonadTrans t)=>Class(tm)A
实例(MonadTrans t)=>Class(t(tm))B
这是可行的,但需要为每个基础实例声明提升实例[…]

这并不是那些默认设置的用途。实例应该如下所示

instance Class m a => Class (StateT s m) a
instance Class m a => Class (MaybeT m) a

等等。

为什么您首先需要一个
类(tm)B
实例?难道这种情况不能被
(MonadTrans t,Class ma)=>Class(tm)a
所涵盖吗?或者将
tm
限制为仅
B
,但不允许
a
tm
一起使用的想法是
B
方法的实现在
tm
中,而且不可能仅在
M
@notBob中定义。我们是否可以假设基本实例集是“封闭的”,即库的用户无法扩展?@danidiaz不,这是无法假设的。虽然我可能是它的唯一用户,但我打算在本模块中只保留最一般的内容,并在其他模块中定义实例。为什么您首先需要
Class(tm)B
实例?难道这种情况不能被
(MonadTrans t,Class ma)=>Class(tm)a
所涵盖吗?或者将
tm
限制为仅
B
,但不允许
a
tm
一起使用的想法是
B
方法的实现在
tm
中,而且不可能仅在
M
@notBob中定义。我们是否可以假设基本实例集是“封闭的”,即库的用户无法扩展?@danidiaz不,这是无法假设的。虽然我可能是它的唯一用户,但我打算在这个模块中只保留最一般的内容,并在其他模块中定义实例。