陷入状态 Monad

2024-04-24

我想使用节点和唯一键的 IntMap 创建一个图形结构。这个话题已经被很好地涵盖了here https://stackoverflow.com/questions/12941625/ids-from-state-monad-in-haskell?lq=1 and here https://stackoverflow.com/questions/6311512/creating-unique-labels-in-haskell。我理解状态 monad 的工作原理,基本上是将 state -> (val,state) 的函数包装在新类型中,这样我们就可以为其创建一个 monad 实例。我已经阅读了很多有关该主题的内容。我似乎仍然无法弄清楚如何在程序执行过程中获得唯一(或只是增量)值。获得一系列连续的 ID 很容易,但是一旦我“runState”退出 monad,我似乎又回到了必须跟踪当前 ID 的地方。我感觉自己被困在单子里了。我考虑的另一个选择是将整个 IntMap 和当前的“下一个”ID 保留为状态,但这似乎非常“势在必行”且极端。This https://stackoverflow.com/questions/5385363/propogation-of-state-monad问题非常相似,但没有得到很多答案(或者也许我只是错过了一些明显的东西)。在程序执行过程中利用状态单子获取唯一 ID 的惯用方法是什么?谢谢。


让我们想象一下我们要IO- 使State单子。那会是什么样子?我们的纯粹Statemonad 只是一个新类型:

s -> (a, s)

嗯,IO在返回最终值之前,版本可能会产生一些副作用,如下所示:

s -> IO (a, s)

这种模式非常常见,它有一个名字,特别是StateT:

newtype StateT s m a = StateT { runStateT :: s -> m (a, s) }

这个名字有一个T最后因为它是一个 monadT变压器。我们称之为m“基本单子”和StateT s m“转变”的单子。

StateT s m只是一个Monad if m is a Monad:

instance (Monad m) => Monad (StateT s m) where {- great exercise -}

然而,除此之外,所有 monad 转换器都实现了MonadTrans类,定义如下:

class MonadTrans t where
    lift :: (Monad m) => m a -> t m a

instance MonadTrans (StateT s) where {- great exercise -}

If t is StateT s, then lift的类型专门用于:

lift :: m a -> StateT s m a

换句话说,它让我们“提升”基础 monad 中的动作,使其成为转换后 monad 中的动作。

因此,对于您的具体问题,您想要StateT (IntMap k v) IO单子,它延伸IO加上额外的State。然后你可以在这个 monad 中编写你的整个程序:

main = flip runStateT (initialState :: IntMap k v) $ do
    m <- get        -- retrieve the map
    lift $ print m  -- lift an IO action
    (k, v) <- lift readLn
    put (insert k v m)

请注意,我仍然使用get and put。那是因为transformers包实现了我描述的所有概念,并且概括了以下签名get and put to be:

get :: (Monad m) => StateT s m s
put :: (Monad m) => s -> StateT s m ()

这意味着它们会自动工作StateT. transformers然后就定义了State as:

type State s = StateT s Identity

这意味着您可以使用get and put对彼此而言State and StateT.

要了解有关 monad 变压器的更多信息,我强烈推荐Monad 变形金刚 - 一步一步 http://www.cs.virginia.edu/~wh5a/personal/Transformers.pdf.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

陷入状态 Monad 的相关文章

随机推荐

  • 当应用程序在后台时使用 uni_links

    我的应用程序具有以下结构 InheritedWidget for dependencies gt Splash Screen Page gt Login Pages gt Main Pages 当应用程序第一次运行时 我可以使用var li
  • 使用流浪文件回答提示?

    是否可以将脚本添加到 Vagrantfile 来回答提示 我正在为 docker 配置一个 ubuntu 盒子 config vm box ubuntu config vm provision shell inline gt sudo ap
  • 更改浏览器选项卡会意外触发焦点事件,尤其是在 Google Chrome 中

    我刚刚意识到焦点事件有一个小问题 显然 当切换到另一个浏览器选项卡然后再次返回时 焦点会被触发 我宁愿不要这样的事情发生 是否可以 直到今天我才意识到这一点 这是一个小演示 http jsfiddle net MJ6qb 1 http js
  • XmlReader AppendChild 未附加相同的子值

    XmlElement updateRecipient doc CreateElement UpdateRecipient XmlElement email doc CreateElement EMAIL XmlElement listID
  • 是否有适用于 IE6 的 JavaScript PNG 修复程序允许 CSS 背景定位?

    我已经看到了一些允许 PNG 图像在 Internet Explorer 6 中具有透明度的修复 但我还没有找到一个也允许您在 CSS 中设置背景位置的修复 如果你使用精灵 那就会破坏交易 我求助于使用 GIF 质量不高 根本不使用透明图像
  • Django QuerySet 何时被评估?

    我读过 django 查询集是懒惰的 但这是否意味着懒惰 因为我可以在一个语句上链接多个操作 或者懒惰 因为查询被延迟到需要结果的时候 例如 以下模拟代码是否执行两个或三个 SQL 查询 query Books objects filter
  • StreamWriter.Flush() 和 StreamWriter.Close() 有什么区别?

    两者在功能上有什么区别StreamWriter Flush and StreamWriter Close 当我的数据没有正确写入文件时 我添加了两个Flush and Close 到我的代码的末尾 然而 我意识到添加either Flush
  • 具有来自包含器类的静态方法调用的 Ruby 模块

    我需要在模块中定义使用包含该模块的类中的方法的常量 module B def self included base class lt lt base CONST self find end end end class A def self
  • 如何确保以编程方式发送的电子邮件不会被自动标记为垃圾邮件?

    这是一个棘手的问题 我一直依赖技术 例如基于许可的电子邮件 即仅发送给您有权发送的人 而不是公然使用spamish术语 最近 我以编程方式发送的一些电子邮件开始被自动混入人们的垃圾邮件文件夹中 我想知道我能对此做些什么 尽管这些特定的电子邮
  • 为什么空 python 正则表达式搜索的返回值是匹配的?

    将空字符串传递给正则表达式对象时 搜索结果是匹配对象而不是 None 因为没有任何东西可以匹配 所以它应该是 None 吗 import re m re search some text if m is None print Returne
  • 从新线程更新 JProgressBar

    如何从另一个线程更新 JProgressBar setValue int 我的第二个目标是用尽可能少的课程来完成它 这是我现在的代码 Part of the main class pp addActionListener new Actio
  • 在 F# 中组合谓词

    F 中是否有逻辑组合谓词的标准方法 例如 假设我有isCar x and isBlue x然后我想要一些能给我的东西 let isBlueCar x isCar x isBlue x 但是使用某种组合而不是调用 可能像 let isBlue
  • 扫描大量BLE标签

    我一直在寻找在一次扫描中扫描大量 BLE 标签 StickNFind 的可能性 我注意到 当我扫描 10 秒时 我可以轻松检测到大约 20 个 BLE 当我将扫描间隔增加到 30 秒左右并尝试扫描大量 BLE 标签时 例如200 个标签 我
  • WPF:无法控制键盘焦点

    这周我遇到了一个让我陷入困境的问题 总而言之 问题是当我左键单击另一个控件时 我无法从代码中将键盘焦点赋予 ComboBox 具体来说 我有一个 CustomControll 它有一个 Scrollview 其中包含另一个 CustomCo
  • 与使用类相比,在 Program.cs/main 中编写代码是否有充分的理由? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在开发一个相当大的应用程序 而我的技术主管和我在某些事情上的看法并不一致 其中之一是关于控制台应用程序 这些应用程序正在从 shell 脚本移植到
  • 无法在我的 Maven 项目中使用依赖项 jboss-javaee-6.0

    我已经使用 JBoss 7 1 1 设置了一个 Maven 项目 我想使用 JavaEE 库 在根 pom xml 中我设置了
  • 实体框架:唯一(非主键)父字段上的复合外键

    我有一个表需要通过其绑定到另一个表Id列 并按其第三个表 Id Code 列 我可以轻松地做SQL服务器同时使用主键和唯一索引 但不知道如何实现它实体框架 如果我把 Key 两列上的属性 那么我无法创建第一个关系 否则 如果我只申请一个 K
  • 适用于 Windows 的二进制 python 包(模块)的无人值守安装

    是否没有合理的方法来执行 Windows 二进制 python 包的脚本安装 不幸的是 似乎几个基本的 Windows python 软件包 如 pywin32 和 py2exe 只能以 EXE 形式提供 而不是以 MSI 形式提供 据我所
  • fopen() 在 Linux 上创建文件失败

    我正在尝试通过创建一个文件fopen 如下 但不创建该文件并让我 Can t create file P S 我在 Linux Ubuntu 上使用 LAMP 服务器 在创建该文件之前我已经尝试过以下命令 sudo chmod R 755
  • 陷入状态 Monad

    我想使用节点和唯一键的 IntMap 创建一个图形结构 这个话题已经被很好地涵盖了here https stackoverflow com questions 12941625 ids from state monad in haskell