MonadReader 没有功能依赖

huangapple go评论65阅读模式
英文:

MonadReader without functional dependency

问题

是否有一个库中的 MonadReader 的版本没有来自 m -> r 的功能依赖?

如果我有一个需要阅读器上下文 ABC 的函数,并且我想要调用一个需要阅读器上下文 AC 的函数,似乎我必须将所有的上下文捆绑到一个结构中,比如 (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 :: ((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.

huangapple
  • 本文由 发表于 2023年7月11日 09:37:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76658232.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定