英文:
MonadReader without functional dependency
问题
是否有一个库中的 MonadReader 的版本没有来自 m -> r 的功能依赖?
如果我有一个需要阅读器上下文 A、B 和 C 的函数,并且我想要调用一个需要阅读器上下文 A 和 C 的函数,似乎我必须将所有的上下文捆绑到一个结构中,比如 (A, B, C),然后将它们拆分并重新组合成 (A, C) 传递给另一个函数。
这似乎与约束通常如何组合相矛盾。
就像我有这样的函数:
f :: (C1 a, C2 a) => a -> a
g :: (C2 a, C3 a) => a -> a
那么
h :: (C1 a, C2 a, C3 a) => a -> a
h = g . f
是完全可以的。
但如果我尝试:
f :: (MonadReader C1 m, MonadReader C2 m) => m a -> m a
g :: (MonadReader C2 m, MonadReader C3 m) => m a -> m a
那么
h :: (MonadReader C1 m, MonadReader C2 m, MonadReader C3 m) => m a -> m a
h = g . f
这将失败,因为有了那个讨厌的功能依赖。
我理解如果没有功能依赖,ask 可能需要类型注释,但在我的情况下,这是一个合理的妥协,特别是当仅仅在其他地方使用 ask 的输出来确定它的类型时。
是否有没有这个功能依赖的 MonadReader 版本?还是我需要自己编写?或者除了手动拆分/重新组合元组之外,是否还有其他方法(在这种情况下,我觉得最好直接将上下文作为第一个参数显式传递)?
英文:
Is there a version of MonadReader in a library somewhere that doesn't have the functional dependency from m -> r?
If I have a function that requires reader contexts A, B and C, and I want to call a function that requires reader contexts A and C, it seems to be that I have bundle all my contexts up into a structure like (A, B, C), split them and recombine them in (A, C) to pass into another function.
This seems to go against how constraints generally compose.
Like if I have a functions:
f :: (C1 a, C2 a) => a -> a
g :: (C2 a, C3 a) => a -> a
Then
h :: (C1 a, C2 a, C3 a) => a -> a
h = g . f
Is perfectly fine.
But if I try:
f :: (MonadReader C1 m, MonadReader C2 m) => m a -> m a
g :: (MonadReader C2 m, MonadReader C3 m) => m a -> m a
Then
h :: (MonadReader C1 m, MonadReader C2 m, MonadReader C3 m) => m a -> m a
h = g . f
this is going to spit the dummy, because of that pesky functional dependency.
I understand that without the functional dependency, ask may require type annotations, but this is a reasonable compromise in my case, particularly when simply using the output of ask elsewhere determines it's type.
Is there a version of MonadReader without this functional dependency? Or do I need to roll my own? Or is there some other approach than just manually pulling apart/putting together tuples (in which case I feel I might as well just pass the context explicitly as the first argument).
答案1
得分: 4
有关此内容,以下是翻译好的部分:
- 通过 
Magnify类型类,可以使用 此处有相关文档 来处理“镜头”相关内容。 
magnify :: ((b -> k c b) -> a -> k c a) -> m c -> n c
- 在较大的环境中运行一个具有 Getter 的单子动作,该动作在其定义之外。[例如,]
 
magnify :: Monoid w => Getter s t -> RWST s w st c -> RWST t w st c
- 
我还开发了 effect-stack 作为一种潜在的替代方法的概念验证,尽管据我所知,目前没有任何用户使用,甚至连我自己都没有使用。
 - 
如果一个变换器堆栈包括两个提供给定效果的变换器,mtl 没有提供一种清晰的方法来区分哪一个是所需的;始终选择最顶层的那个。
 - 
该包提供了一些工具,可以在不被迫选择特定变换器堆栈的情况下进行消歧义处理。
 
英文:
There's lensy stuff for this via the Magnify type class.
>     magnify :: ((b -> k c b) -> a -> k c a) -> m c -> n c
>
> Run a monadic action in a larger environment than it was defined in, using a Getter. [For example,]
>
>     magnify :: Monoid w => Getter s t -> RWST s w st c -> RWST t w st c
I've also developed effect-stack as a sort of proof-of-concept alternative approach, though as far as I know there are currently exactly zero users -- not even me.
> If a transformer stack includes two transformers that provide the given effect, mtl does not provide a clean way to disambiguate which one is wanted; the topmost one is always chosen.
>
> This package provides tools for disambiguating without being forced to choose a particular transformer stack.
答案2
得分: 1
mtl-unleashed 在这里完全符合要求。
英文:
Answering my own question, mtl-unleashed fits exactly the bill here.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论