英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论