问题标签 [monad-transformers]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
3 回答
734 浏览

haskell - 在 snap 中使用 reader monad(或在 snap 中使用 monad 转换器)

有人可以展示如何在 reader monad 中使用 snap monad 吗?单子变压器让我感到困惑。(或者,我很乐意接受有关 monad 转换器的教程的建议,以及看到光明并最终了解它们的方法。)

编辑:哎呀;忘记具体说明我实际上要做什么,而不是就特定的事情寻求帮助。战略,而不是战术。我特别想在所有处理程序之间共享一个数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。似乎 reader monad 将是实现这一目标的方法。

0 投票
2 回答
585 浏览

haskell - 为什么包装 Data.Binary.Put monad 会造成内存泄漏?(第2部分)

正如我之前的问题一样,我试图将 Data.Binary.Put monad 包装到另一个 monad 中,以便稍后我可以问它诸如“它将写入多少字节”或“文件中的当前位置是什么”之类的问题.

以前,我认为理解为什么它在使用琐碎的(IdentityT?)包装器时会泄漏内存将引导我解决我的问题。但是,即使你们帮助我解决了琐碎包装器的问题,用像 StateT 或 WriterT 这样有用的东西来包装它仍然会消耗太多内存(并且通常会崩溃)。

例如,这是我试图包装它的一种方式,它会泄漏大量输入的内存:

是演示问题的更完整的代码示例。

我想知道的是:

  1. 导致内存泄漏的程序内部发生了什么?
  2. 我能做些什么来修复它?

对于我的第二个问题,我想我应该更详细地解释我希望数据在磁盘上看到的内容:它基本上是一个树结构,其中树的每个节点都表示为其子节点的偏移表(加上一些额外的数据)。因此,要计算第 n 个子节点的偏移量到偏移表中,我需要知道子节点 0 到 n-1 的大小加上当前偏移量(为简化起见,假设每个节点都有固定数量的子节点)。

感谢您的关注。

更新:感谢 nominolo,我现在可以创建一个环绕 Data.Binary.Put 的 monad,跟踪当前偏移量并且几乎不使用内存。这是通过放弃使用 StateT 转换器来支持使用 Continuations 的不同状态线程机制来完成的。

像这样:

但是,我仍然无法跟踪 MyPut 将在磁盘上写入多少字节。特别是,我需要一个带有这样签名的函数:

者p>

我的方法是将 MyPut monad 包装在 WriterT 转换器中(类似这样的东西)。但这又开始消耗过多的内存。正如 sclv 在 nominolos 答案下的评论中提到的那样,WriterT 以某种方式抵消了延续的影响。他还提到应该可以直接从我已经拥有的 MyPut monad 中获取大小,但是我所有这样做的尝试都以不可编译的代码或无限循环结束:-|。

有人可以进一步帮助吗?

0 投票
5 回答
2865 浏览

haskell - 同一个单子变压器的不同排序有什么区别?

我正在尝试定义一个 API 来表达我的程序中的特定类型的过程。

有状态,由 ID 到记录的映射组成:

基本操作有以下三种:

我对这些操作有几个目标:

  • 过程可以对哪些记录可用做出假设(与原始Map.lookup调用不同),如果它们的任何假设是错误的,则整个过程会返回失败。
  • 可以使用(来自类 Alternative)将一系列过程链接在一起<|>,以便回退到做出不同假设的过程。(类似于 STM 的orElse

鉴于这些目标,我相信我想要一些 theStateMaybemonad 的组合。

我无法弄清楚Maybe和的两个排序如何State表现不同。谁能解释两个排序之间的行为差​​异?

另外,如果您发现我最初的想法有问题(也许我过度设计),请随时指出。

结论: 所有三个答案都有帮助,但有一个共同的想法帮助我决定我想要哪种顺序。通过查看runMaybeT/的返回类型runStateT,很容易看出哪个组合具有我正在寻找的行为。(就我而言,我想要返回类型Maybe (ProcedureState, a))。

0 投票
4 回答
2204 浏览

haskell - 如何将树数据结构保存到 Haskell 中的二进制文件

我正在尝试使用 Haskell 将一个简单(但相当大)的树结构保存到二进制文件中。结构看起来像这样:

这就是我需要磁盘上的数据的方式:

  1. 每个节点都以其子节点的四个 32 位偏移量开始,然后跟随子节点。
  2. 我不太关心叶子,假设它只是 n 个连续的 32 位数字。
  3. 出于实际目的,我需要一些节点标签或其他一些额外的数据,但现在我也不关心那么多。

在我看来,Haskellers 在编写二进制文件时的首选是 Data.Binary.Put 库。但是这样一来,我在第 1 个项目符号中遇到了问题。特别是,当我将节点写入文件时,要记下子偏移量,我需要知道我当前的偏移量和每个子节点的大小。

这不是 Data.Binary.Put 提供的东西,所以我认为这一定是 Monad 转换器的完美应用。但是,尽管它听起来很酷而且很实用,但到目前为止我还没有成功地使用这种方法。

我问了另外两个问题,我认为它们可以帮助我解决这里这里的问题。我必须说,每次我收到非常好的答案,帮助我进一步进步,但不幸的是我仍然无法整体解决问题。

是我到目前为止所得到的,它仍然泄漏太多内存而不实用。

我很想拥有使用这种功能方法的解决方案,但也会感谢任何其他解决方案。

0 投票
2 回答
5517 浏览

haskell - Haskell 中的 Goto:谁能解释这种看似疯狂的 continuation monad 使用效果?

这个线程 (Control.Monad.Cont fun, 2005),Tomasz Zielonka 引入了一个函数(Thomas Jäger 以清晰而优美的方式评论)。Tomasz 接受 callCC 主体的参数(一个函数)并将其返回以供以后使用,具有以下两个定义:

Haskellwiki中也提到了这些。使用它们,您可以类似于 haskell 中的 goto 语义,看起来非常酷:

这将打印数字 0 到 10。

有趣的地方来了。我将它与 Writer Monad 一起使用来解决某个问题。我的代码如下所示:

当您编译并运行此代码时,输​​出为:

数字 0 到 3 在这个例子的深邃黑暗中被吞没了。

现在,在“Real World Haskell”中,奥沙利文、戈尔岑和斯图尔特状态

“堆叠 monad 转换器类似于组合函数。如果我们改变应用函数的顺序,然后得到不同的结果,我们不会感到惊讶。monad 转换器也是如此。” (真实世界的 Haskell,2008 年,第 442 页)

我想出了交换上面的变压器的想法:

但是,这不会编译,因为在 Control.Monad.Cont 中没有 MonadWriter 的实例定义(这就是我最近问这个问题的原因。)

我们添加一个实例,离开监听并传递未定义:

添加这些行,编译并运行。所有数字都打印出来。

前面的例子发生了什么?

0 投票
1 回答
515 浏览

haskell - 为什么将 Data.Binary.Put monad 更改为转换器会导致内存泄漏?

我正在尝试将 Data.Binary.PutM monad 修改为 monad 转换器。所以我从改变它的定义开始

然后当然我改变了return>>=函数的实现:

从:

到:

好像 PutM monad 只是一个 Writer monad。不幸的是,这(再次)造成了空间泄漏。我很清楚(或者是吗?)ghc 正在推迟某个地方的评估,但我试图按照一些教程的建议$!而不是$任何地方放置,但这并没有帮助。另外,如果内存分析器向我显示的内容是这样的,我不确定它有什么帮助:

内存配置文件.

为了完整起见,这是我在使用原始 Data.Binary.Put monad 时得到的内存配置文件:

原始内存配置文件

如果有兴趣,这里是我用来测试它的代码,我用来编译、运行和创建内存配置文件的行是:

我希望我的内存泄漏问题不会惹恼任何人。我发现互联网上没有很多关于这个主题的好资源,这让新手一无所知。

感谢您的关注。

0 投票
2 回答
337 浏览

monads - 为什么要为 monad 定义单位自然变换 - 这不是 monad 作为内函子的定义所暗示的吗?

  1. monad 被定义为类别 C 上的 endofunctor。假设 C 具有类型 int 和 bool 以及其他构造类型作为对象。现在让我们考虑在这个类别上定义的列表单子。

根据它的定义 list then 是一个内函子,它映射(这可以解释为一个函数吗?)一个 int 类型到 List[int] 和 bool 到 List[bool] 和映射(又是一个函数?)一个态射 int - > bool to List[int] -> List[bool]

所以,到目前为止,这是有道理的。但是让我深感困惑的是需要伴随它的自然变换的附加定义:Unit...将 int 转换为 List[int] (List 函子的定义不是已经暗示了这一点吗?这是我遇到的一个主要困惑

湾。List 函子是否总是必须被理解为从 int 到 List[int] 而不是从 int 到 List[bool] 的映射?

C。单位自然转换 int 到 List[int] 是否不同于将 List 定义为函子所暗示的从 int 到 List[int] 的映射?我想这只是对我之前问题的重新陈述。

0 投票
2 回答
755 浏览

haskell - monad 转换器中的内部 monad 是否有“replicateM”功能?

假设我有这样的事情:

我脑子里想的是一个时间过程的模拟,在这个过程中我有将存储的参数,Environment动态状态将存储在MyState,我希望在模拟的每个时间步收集的信息将存储在Report

现在,我不想运行此模拟的许多步骤并获取每个时间步骤的报告列表。

我通常在没有 a 的情况下执行此操作,ReaderT并用于传递如下参数:

然后我会这样做:

我对liftand的类型感到困惑replicateM。是否有一种组合可以复制State MyState变压器内部的单子?

将来我会替换ReaderT Environment (State MyState) ReportforReaderT Environment (StateT MyState (Rand StdGen)) Report所以最好在拥有这种怪物类型之前把事情做好:(。

编辑:作为一个附带问题 - 有没有比使用更好的策略ReaderT Environment (State MyState) Report

0 投票
4 回答
396 浏览

haskell - 接口抽象设计

目前,我尝试编写一个小游戏程序(Skat)作为一个爱好项目。Skat 是一个花样游戏,两个玩家对抗一个玩家。由于有不同种类的播放器(本地播放器、网络播放器、计算机等),我想抽象出播放器的接口。

我的基本想法是使用 typeclass Player,它定义了所有类型的事情,玩家必须做和知道的(打牌,得到关于谁赢了把戏的通知等)。然后,整个游戏只是由一个函数playSkat :: (Player a, Player b, Player c) => a -> b -> c -> IO ()where完成ab并且c可能是不同类型的玩家。然后玩家可能会以实现定义的方式做出反应。本地玩家会在他的终端上收到一些消息,网络玩家可能会通过网络发送一些信息,而计算机玩家可能会计算新策略。

因为玩家可能想要做一些 IO 并且肯定想要有某种状态来跟踪私人事物,所以它必须生活在某种 Monad 中。所以我想像这样定义Player类:

这种模式似乎与状态转换器非常相似,但我不知道如何处理它。如果我把它写成 IO 之上的一个额外的 monad-transformer,那么一天结束时我就有了三个不同的 monad。我怎样才能以一种好的方式编写这个抽象?

澄清一下,我需要的是,通常的控制流程应该是这样的:
玩花样时,第一个玩家出牌,然后是第二个,最后是第三个。为此,逻辑需要playCard为每个玩家执行函数 trice。之后,逻辑决定哪位玩家获胜,并将获胜者的信息发送给所有玩家。

0 投票
1 回答
4015 浏览

haskell - Monad 转换器库 - 使用哪一个?

Hackage 上有许多不同的 monad 转换器库。一些似乎比其他人更受关注。仅举几例:mtl(由于某种原因,当前版本取决于转换器)、转换器、monadLib、monads-tf、mtlx、contstuff。

应该首选哪一个,为什么?它们的独特之处是什么?性能呢?