无函数依赖的MonadReader:是否有现成库实现?
无函数依赖的MonadReader解决方案
现成库选项
有现成库能满足需求:reader-simple。它提供的MonadReader类没有m -> r的函数依赖,允许同一个Monad实例同时满足多个不同r的MonadReader约束,完全适配你提到的约束组合场景。使用时ask可能需要类型注解(比如ask @A),但正如你所说,当ask的输出用途能明确类型时,类型推断也能自动推导,这个妥协完全可行。
自行实现方案
如果不想引入额外依赖,也可以自己定义无函数依赖的MonadReader类:
class Monad m => MonadReader r m where ask :: m r local :: (r -> r) -> m a -> m a
然后为你的上下文载体(比如ReaderT (A,B,C) m)实现多个实例:
instance Monad m => MonadReader A (ReaderT (A,B,C) m) where ask = asks (\(a,_,_) -> a) local f = mapReaderT (\(a,b,c) -> (f a, b, c)) instance Monad m => MonadReader B (ReaderT (A,B,C) m) where ask = asks (\(_,b,_) -> b) local f = mapReaderT (\(a,b,c) -> (a, f b, c)) instance Monad m => MonadReader C (ReaderT (A,B,C) m) where ask = asks (\(_,_,c) -> c) local f = mapReaderT (\(a,b,c) -> (a, b, f c))
这样就能直接组合你示例中的f和g,无需手动拆分重组元组上下文。
其他替代思路
除了上述两种方式,还可以考虑使用效应系统,比如polysemy或freer-effects。这类库的效应组合天然支持多个类似Reader的上下文需求,不需要依赖类型类的函数依赖就能实现灵活的上下文组合,不过学习成本会比直接用无函数依赖的MonadReader高一些。
内容的提问来源于stack exchange,提问作者Clinton
相关产品推荐
相关产品推荐

