问题标签 [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.
haskell - 在 snap 中使用 reader monad(或在 snap 中使用 monad 转换器)
有人可以展示如何在 reader monad 中使用 snap monad 吗?单子变压器让我感到困惑。(或者,我很乐意接受有关 monad 转换器的教程的建议,以及看到光明并最终了解它们的方法。)
编辑:哎呀;忘记具体说明我实际上要做什么,而不是就特定的事情寻求帮助。战略,而不是战术。我特别想在所有处理程序之间共享一个数据库连接/池,而不必在指定路由时显式传递该数据库连接/池。似乎 reader monad 将是实现这一目标的方法。
haskell - 为什么包装 Data.Binary.Put monad 会造成内存泄漏?(第2部分)
正如我之前的问题一样,我试图将 Data.Binary.Put monad 包装到另一个 monad 中,以便稍后我可以问它诸如“它将写入多少字节”或“文件中的当前位置是什么”之类的问题.
以前,我认为理解为什么它在使用琐碎的(IdentityT?)包装器时会泄漏内存将引导我解决我的问题。但是,即使你们帮助我解决了琐碎包装器的问题,用像 StateT 或 WriterT 这样有用的东西来包装它仍然会消耗太多内存(并且通常会崩溃)。
例如,这是我试图包装它的一种方式,它会泄漏大量输入的内存:
这是演示问题的更完整的代码示例。
我想知道的是:
- 导致内存泄漏的程序内部发生了什么?
- 我能做些什么来修复它?
对于我的第二个问题,我想我应该更详细地解释我希望数据在磁盘上看到的内容:它基本上是一个树结构,其中树的每个节点都表示为其子节点的偏移表(加上一些额外的数据)。因此,要计算第 n 个子节点的偏移量到偏移表中,我需要知道子节点 0 到 n-1 的大小加上当前偏移量(为简化起见,假设每个节点都有固定数量的子节点)。
感谢您的关注。
更新:感谢 nominolo,我现在可以创建一个环绕 Data.Binary.Put 的 monad,跟踪当前偏移量并且几乎不使用内存。这是通过放弃使用 StateT 转换器来支持使用 Continuations 的不同状态线程机制来完成的。
像这样:
但是,我仍然无法跟踪 MyPut 将在磁盘上写入多少字节。特别是,我需要一个带有这样签名的函数:
者p>我的方法是将 MyPut monad 包装在 WriterT 转换器中(类似这样的东西)。但这又开始消耗过多的内存。正如 sclv 在 nominolos 答案下的评论中提到的那样,WriterT 以某种方式抵消了延续的影响。他还提到应该可以直接从我已经拥有的 MyPut monad 中获取大小,但是我所有这样做的尝试都以不可编译的代码或无限循环结束:-|。
有人可以进一步帮助吗?
haskell - 同一个单子变压器的不同排序有什么区别?
我正在尝试定义一个 API 来表达我的程序中的特定类型的过程。
有状态,由 ID 到记录的映射组成:
基本操作有以下三种:
我对这些操作有几个目标:
- 过程可以对哪些记录可用做出假设(与原始
Map.lookup
调用不同),如果它们的任何假设是错误的,则整个过程会返回失败。 - 可以使用(来自类 Alternative)将一系列过程链接在一起
<|>
,以便回退到做出不同假设的过程。(类似于 STM 的orElse
)
鉴于这些目标,我相信我想要一些 theState
和Maybe
monad 的组合。
我无法弄清楚Maybe
和的两个排序如何State
表现不同。谁能解释两个排序之间的行为差异?
另外,如果您发现我最初的想法有问题(也许我过度设计),请随时指出。
结论:
所有三个答案都有帮助,但有一个共同的想法帮助我决定我想要哪种顺序。通过查看runMaybeT
/的返回类型runStateT
,很容易看出哪个组合具有我正在寻找的行为。(就我而言,我想要返回类型Maybe (ProcedureState, a)
)。
haskell - 如何将树数据结构保存到 Haskell 中的二进制文件
我正在尝试使用 Haskell 将一个简单(但相当大)的树结构保存到二进制文件中。结构看起来像这样:
这就是我需要磁盘上的数据的方式:- 每个节点都以其子节点的四个 32 位偏移量开始,然后跟随子节点。
- 我不太关心叶子,假设它只是 n 个连续的 32 位数字。
- 出于实际目的,我需要一些节点标签或其他一些额外的数据,但现在我也不关心那么多。
在我看来,Haskellers 在编写二进制文件时的首选是 Data.Binary.Put 库。但是这样一来,我在第 1 个项目符号中遇到了问题。特别是,当我将节点写入文件时,要记下子偏移量,我需要知道我当前的偏移量和每个子节点的大小。
这不是 Data.Binary.Put 提供的东西,所以我认为这一定是 Monad 转换器的完美应用。但是,尽管它听起来很酷而且很实用,但到目前为止我还没有成功地使用这种方法。
我问了另外两个问题,我认为它们可以帮助我解决这里和这里的问题。我必须说,每次我收到非常好的答案,帮助我进一步进步,但不幸的是我仍然无法整体解决问题。
这是我到目前为止所得到的,它仍然泄漏太多内存而不实用。
我很想拥有使用这种功能方法的解决方案,但也会感谢任何其他解决方案。
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 的实例定义(这就是我最近问这个问题的原因。)
我们添加一个实例,离开监听并传递未定义:
添加这些行,编译并运行。所有数字都打印出来。
前面的例子发生了什么?
haskell - 为什么将 Data.Binary.Put monad 更改为转换器会导致内存泄漏?
我正在尝试将 Data.Binary.PutM monad 修改为 monad 转换器。所以我从改变它的定义开始
到
然后当然我改变了return和>>=函数的实现:
从:
到:
好像 PutM monad 只是一个 Writer monad。不幸的是,这(再次)造成了空间泄漏。我很清楚(或者是吗?)ghc 正在推迟某个地方的评估,但我试图按照一些教程的建议$!
而不是$
任何地方放置,但这并没有帮助。另外,如果内存分析器向我显示的内容是这样的,我不确定它有什么帮助:
.
为了完整起见,这是我在使用原始 Data.Binary.Put monad 时得到的内存配置文件:
如果有兴趣,这里是我用来测试它的代码,我用来编译、运行和创建内存配置文件的行是:
我希望我的内存泄漏问题不会惹恼任何人。我发现互联网上没有很多关于这个主题的好资源,这让新手一无所知。
感谢您的关注。
monads - 为什么要为 monad 定义单位自然变换 - 这不是 monad 作为内函子的定义所暗示的吗?
- 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] 的映射?我想这只是对我之前问题的重新陈述。
haskell - monad 转换器中的内部 monad 是否有“replicateM”功能?
假设我有这样的事情:
我脑子里想的是一个时间过程的模拟,在这个过程中我有将存储的参数,Environment
动态状态将存储在MyState
,我希望在模拟的每个时间步收集的信息将存储在Report
。
现在,我不想运行此模拟的许多步骤并获取每个时间步骤的报告列表。
我通常在没有 a 的情况下执行此操作,ReaderT
并用于传递如下参数:
然后我会这样做:
我对lift
and的类型感到困惑replicateM
。是否有一种组合可以复制State MyState
变压器内部的单子?
将来我会替换ReaderT Environment (State MyState) Report
forReaderT Environment (StateT MyState (Rand StdGen)) Report
所以最好在拥有这种怪物类型之前把事情做好:(。
编辑:作为一个附带问题 - 有没有比使用更好的策略ReaderT Environment (State MyState) Report
?
haskell - 接口抽象设计
目前,我尝试编写一个小游戏程序(Skat)作为一个爱好项目。Skat 是一个花样游戏,两个玩家对抗一个玩家。由于有不同种类的播放器(本地播放器、网络播放器、计算机等),我想抽象出播放器的接口。
我的基本想法是使用 typeclass Player
,它定义了所有类型的事情,玩家必须做和知道的(打牌,得到关于谁赢了把戏的通知等)。然后,整个游戏只是由一个函数playSkat :: (Player a, Player b, Player c) => a -> b -> c -> IO ()
where完成a
,b
并且c
可能是不同类型的玩家。然后玩家可能会以实现定义的方式做出反应。本地玩家会在他的终端上收到一些消息,网络玩家可能会通过网络发送一些信息,而计算机玩家可能会计算新策略。
因为玩家可能想要做一些 IO 并且肯定想要有某种状态来跟踪私人事物,所以它必须生活在某种 Monad 中。所以我想像这样定义Player
类:
这种模式似乎与状态转换器非常相似,但我不知道如何处理它。如果我把它写成 IO 之上的一个额外的 monad-transformer,那么一天结束时我就有了三个不同的 monad。我怎样才能以一种好的方式编写这个抽象?
澄清一下,我需要的是,通常的控制流程应该是这样的:
玩花样时,第一个玩家出牌,然后是第二个,最后是第三个。为此,逻辑需要playCard
为每个玩家执行函数 trice。之后,逻辑决定哪位玩家获胜,并将获胜者的信息发送给所有玩家。
haskell - Monad 转换器库 - 使用哪一个?
Hackage 上有许多不同的 monad 转换器库。一些似乎比其他人更受关注。仅举几例:mtl(由于某种原因,当前版本取决于转换器)、转换器、monadLib、monads-tf、mtlx、contstuff。
应该首选哪一个,为什么?它们的独特之处是什么?性能呢?