0

这个问题可以认为是后续问题

将具有“MonadIO”类型变量的类实例提升到转换后的 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

. 我想要的是一种将任何实例提升到自身或在变压器堆栈中更高的方法,就像liftIOIO. 我最初的想法是定义一个提升实例

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

. 这可行,但是需要为每个基本实例声明提升实例,所以我很好奇;有没有其他方法可以在不使用重叠实例的情况下解决这个问题?

4

1 回答 1

2

你写

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

等等。

于 2020-10-22T17:30:06.843 回答