有什么方法可以创建 unmemo-monad 吗?

2024-03-26

假设有人编写了一个下棋或解数独的程序。在这种程序中,使用表示游戏状态的树结构是有意义的。

这棵树会非常大,“几乎是无限的”。这本身并不是一个问题,因为 Haskell 支持无限数据结构。

一个常见的无限数据结构示例:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)

节点仅在第一次使用时分配,因此列表占用有限的内存。如果不保留对其头部的引用,也可以迭代无限列表,从而允许垃圾收集器收集不再需要的部分。

回到树的例子 - 假设对树进行一些迭代,如果仍然需要树的根,则迭代的树节点可能不会被释放(例如,在迭代加深搜索中,树将被迭代多次因此需要保留根)。

我想到的这个问题的一个可能的解决方案是使用“unmemo-monad”。

我将尝试使用单子列表来演示这个单子应该做什么:

import Control.Monad.ListT (ListT)  -- cabal install List
import Data.Copointed  -- cabal install pointed
import Data.List.Class
import Prelude hiding (enumFromTo)

nums :: ListT Unmemo Int  -- What is Unmemo?
nums = enumFromTo 0 1000000

main = print $ div (copoint (foldlL (+) 0 nums)) (copoint (lengthL nums))

Using nums :: [Int],该程序将占用大量内存作为对nums需要由lengthL nums当它被迭代时foldlL (+) 0 nums.

的目的Unmemo是为了让运行时不让节点迭代。

我尝试使用((->) ()) as Unmemo,但它产生的结果与nums :: [Int]确实 - 该程序使用了大量内存,通过运行它可以明显看出+RTS -s.

有没有办法实施Unmemo这就是我想要的吗?


与流相同的技巧——不直接捕获余数,而是捕获一个值和一个产生余数的函数。您可以根据需要在此基础上添加记忆。

data UTree a = Leaf a | Branch a (a -> [UTree a]) 

我现在没有心情去准确地弄清楚它,但我确信这种结构自然会出现,就像一个相当简单的函子上的 cofree comonad 一样。

Edit

找到了:http://hackage.haskell.org/packages/archive/comonad-transformers/1.6.3/doc/html/Control-Comonad-Trans-Stream.html http://hackage.haskell.org/packages/archive/comonad-transformers/1.6.3/doc/html/Control-Comonad-Trans-Stream.html

或者这可能更容易理解:http://hackage.haskell.org/packages/archive/streams/0.7.2/doc/html/Data-Stream-Branching.html http://hackage.haskell.org/packages/archive/streams/0.7.2/doc/html/Data-Stream-Branching.html

无论哪种情况,诀窍是你的f可以选择类似的东西data N s a = N (s -> (s,[a]))为一个适当的s(s 是流的状态参数的类型——展开的种子,如果你愿意的话)。这可能不完全正确,但应该做一些接近的事情......

但当然,对于实际工作,您可以放弃所有这些,直接按照上面的方式编写数据类型。

Edit 2

下面的代码说明了这如何阻止共享。请注意,即使在没有共享的版本中,配置文件中也存在驼峰,表明总和和长度调用没有在恒定空间中运行。我想我们需要一个明确的严格积累来消除这些。

{-# LANGUAGE DeriveFunctor #-}
import Data.Stream.Branching(Stream(..))
import qualified Data.Stream.Branching as S
import Control.Arrow
import Control.Applicative
import Data.List

data UM s a = UM (s -> Maybe a) deriving Functor
type UStream s a = Stream (UM s) a

runUM s (UM f) = f s
liftUM x = UM $ const (Just x)
nullUM = UM $ const Nothing

buildUStream :: Int -> Int -> Stream (UM ()) Int
buildUStream start end = S.unfold (\x -> (x, go x)) start
    where go x
           | x < end = liftUM (x + 1)
           | otherwise = nullUM

sumUS :: Stream (UM ()) Int -> Int
sumUS x = S.head $ S.scanr (\x us -> maybe 0 id (runUM () us) + x) x

lengthUS :: Stream (UM ()) Int -> Int
lengthUS x = S.head $ S.scanr (\x us -> maybe 0 id (runUM () us) + 1) x

sumUS' :: Stream (UM ()) Int -> Int
sumUS' x = last $ usToList $ liftUM $ S.scanl (+) 0  x

lengthUS' :: Stream (UM ()) Int -> Int
lengthUS' x = last $ usToList $ liftUM $ S.scanl (\acc _ -> acc + 1) 0 x

usToList x = unfoldr (\um -> (S.head &&& S.tail) <$> runUM () um) x

maxNum = 1000000
nums = buildUStream 0 maxNum

numsL :: [Int]
numsL = [0..maxNum]

-- All these need to be run with increased stack to avoid an overflow.

-- This generates an hp file with two humps (i.e. the list is not shared)
main = print $ div (fromIntegral $ sumUS' nums) (fromIntegral $ lengthUS' nums)

-- This generates an hp file as above, and uses somewhat less memory, at the cost of
-- an increased number of GCs. -H helps a lot with that.
-- main = print $ div (fromIntegral $ sumUS nums) (fromIntegral $ lengthUS nums)

-- This generates an hp file with one hump (i.e. the list is shared)
-- main = print $ div (fromIntegral $ sum $ numsL) (fromIntegral $ length $ numsL)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有什么方法可以创建 unmemo-monad 吗? 的相关文章

  • 移动列表中特定元素的简单函数

    我是 Haskell 的新手 我正在尝试弄清楚如何创建一个函数 shift Eq a gt a gt a gt Int gt a shift x h t z 输入 一个通用列表和一个相同类型的元素 x 前提条件 元素x存在于列表中 Outp
  • 如何提高 MongoDB 中 update() 和 save() 的性能?

    我正在寻找有关如何在以下情况下提高数据库性能的提示 作为示例应用程序 我今天编写了一个相当简单的应用程序 它使用 Twitter 流 API 来搜索某些关键字 然后将结果存储在 MongoDB 中 该应用程序是用 Node js 编写的 我
  • Haskell 中的异构多态性(正确方法)

    让一个模块来抽象Area操作 错误的定义 class Area someShapeType where area someShapeType gt Float module utilities sumAreas Area someShape
  • 在 Android 谷歌地图中绘制 4K 折线

    我现在正在开发一个适用于 Android 设备的应用程序 主要功能是在地图上绘制折线以显示城市中每条街道的交通情况 不幸的是 当我绘制大约 3K 折线时 数量会根据屏幕尺寸和缩放级别而减少 我的地图变得非常慢 我没有提及绘制所有线条的时间
  • PHP include():文件大小和性能

    一个没有经验的PHP问题 我有一个 PHP 脚本文件 我需要在不同页面的很多地方多次包含该文件 我可以选择将包含的文件分解为几个较小的文件 并根据需要包含这些文件 或者 我可以将它们全部保存在一个 PHP 文件中 我想知道在这种情况下使用较
  • 我可以在 pandas 中执行动态行累加吗?

    如果我有以下数据框 如下导出 df pd DataFrame np random randint 0 10 size 10 1 0 0 0 1 2 2 8 3 1 4 0 5 0 6 7 7 0 8 2 9 2 有没有有效的方法cumsum
  • 数百个空闲线程的影响

    我正在考虑使用可能数百个线程来实现通过网络管理设备的任务 这是一个在带有 Linux 内核的 powerpc 处理器上运行的 C 应用程序 在每个任务进行同步以将数据从设备复制到任务的初始阶段之后 任务变得空闲 并且仅在收到警报或需要更改一
  • 使用 NSMutableDictionary 与 NSMutableArray 造成的性能损失>

    我正在考虑使用 NSMutableDictionary 代替我当前的 NSMutableArray 这主要是出于 KVC KVO 的原因 该集合将在我的绘图方法的内循环中经历严重的变化 如果我继续进行此替换 性能是否会受到重大影响 干杯 道
  • 在 Haskell 中将字节转换为 Int64s/Floats/Doubles

    我正在尝试解析 Haskell 中的二进制文件格式 Apple 的二进制属性列表格式 该格式所需的内容之一是将字节序列视为 a 无符号 1 2 或 4 字节整数 b 有符号 8 字节整数 c 32 位floats d 64 位doubles
  • 如何有效地计算 Perl 中覆盖给定范围的范围?

    我有一个大约 30k 范围的数据库 每个范围都作为一对起点和终点给出 12 80 34 60 34 9000 76 743 我想编写一个 Perl 子例程来表示一个范围 不是来自数据库 并返回数据库中完全 包含 给定范围的范围数 例如 如果
  • 在未排序的整数列表中最优搜索 k 个最小值

    我刚刚接受采访时提出了一个问题 我很好奇答案应该是什么 问题本质上是 假设您有一个包含 n 个整数的未排序列表 您如何找到此列表中的 k 个最小值 也就是说 如果您有一个 10 11 24 12 13 列表并且正在寻找 2 个最小值 您将得
  • 如何使用 Haskell 中的 thyme 库从 Int 值创建 UTCTime?

    我有年 月 日 小时和分钟值 所有这些都是类型Int 我怎样才能将它们转换为UTCTime or UniversalTime 需要导入以下内容 import Control Lens import Data Thyme Clock impo
  • 通过 Emacs 评估 ghci 或 Hugs 中的缓冲区

    在 Emacs 中使用 sml mode 我已经能够使用以下命令将缓冲区内容直接发送到较差的 SML 进程C c C b 现在我只想用 Haskell 做同样的事情 Haskell 模式似乎不支持这一点 所以我想知道 使用 Emacs 和
  • 在 Matlab 中快速加载大块二进制文件

    我有一些相当大的 int16 格式的数据文件 256 个通道 大约 75 1 亿个样本 每个文件约 40 50 GB 左右 它以平面二进制格式编写 因此结构类似于 CH1S1 CH2S1 CH3S1 CH256S1 CH1S2 CH2S2
  • 将系统命令的结果绑定到 Haskell 中的变量

    如何在 Haskell 中运行系统命令and将其结果 即标准输出 绑定到变量 在伪 Haskell 中 我正在寻找类似以下内容的内容 import System Process main do output lt callCommand e
  • 在 JavaScript 中嵌套“switch”案例:有速度优势吗?

    这里有新手问题 我有一个包含大量字符串的 开关 像这样按字母顺序拆分是否有速度优势 switch myString substring 0 1 case a switch myString case a string beginning w
  • Haskell Cabal 包 - 找不到 Paths_ 模块

    我正在开发一个 Haskell 项目 Happstack 服务器 Blaze HTML 前端作为主要库 我想添加一个静态数据目录 看起来你可以使用 Cabal 使用自动生成的Path
  • 访问函数中的环境

    In main我可以读取我的配置文件 并将其提供为runReader somefunc myEnv正好 但somefunc不需要访问myEnv读者提供 链中的下一对也没有提供 需要 myEnv 中某些内容的函数是一个微小的叶函数 如何在不将
  • glBlitFramebuffer 渲染缓冲区和渲染全屏纹理哪个更快?

    哪个更快更高效 使用 OpenGL 纹理作为 CUDA 表面并在四边形上渲染 新样式 使用渲染缓冲区作为 CUDA 表面并使用 glBlitFramebuffer 进行渲染 None
  • PrintStream是有缓冲的,但是flush不会降低性能,而BufferedOutputStream会加速性能

    我预计由于 PrintStream 是缓冲的 通过在每次 print 之后添加刷新操作 速度性能应该会显着降低 但事实并非如此 如下面的代码片段所示 此外 将 PrintStream 包裹在 BufferedOutputStream 周围可

随机推荐

  • Rails 用范围扩展领域,PG 不喜欢它

    我有一个小部件模型 小部件属于 Store 模型 Store 模型属于 Area 模型 Area 模型属于 Company 在公司模型中 我需要找到所有关联的小部件 简单的 class Widget lt ActiveRecord Base
  • 如何子类化 UITextField 并重写 drawPlaceholderInRect 来更改占位符颜色

    我有一个 3UITextField与占位符文本集 在其中之一UITextField我希望占位符文本为红色 现在 在谷歌搜索之后 似乎最好的方法是子类化 UITextField 并覆盖drawPlaceholderInRect 我如何进行子类
  • 在只有一个键的哈希中查找键名?

    如果我有一个哈希 my h secret gt 1 我知道这只是哈希中的一个键 但我不知道它叫什么 然后我是否必须迭代该哈希 my key foreach my i keys h key h i 或者有更好的方法来获取密钥的名称吗 A 列表
  • 如何从另一个分支获取一个文件

    我有一个main带有名为的文件的分支app js 我对此文件进行了更改experiment branch 我只想应用所做的更改app js from experiment到main branch git checkout main firs
  • mov ah、word_variable 上的“无效指令操作数”以及在 16 位数字上使用 imul

    这是我想要实现的目标 a x b x a y b y a z b z 我正在尝试在汇编中创建一个宏来执行上述计算 我在用WORDs 代表我所有的号码 这是我的代码 dotProduct MACRO A X A Y A Z B X B Y B
  • 在沙箱中运行插件

    我正在设计一个 C C 系统 可以使用各种插件进行扩展 有一个定义良好的 C 公共 API 主要适用于 const char 和其他指针类型 插件被编译成 so 或 dll 文件 主应用程序在启动时加载它们 然后根据请求卸载或重新加载它们
  • Java 的单文件、持久、排序键值存储(Berkeley DB 的替代方案)[关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Berkeley DB JE 许可可能是交易杀手 我有一个面向一小部分客户的 Java 应用程序 但由
  • 如何使 .NET 反射与动态生成的对象一起工作? [复制]

    这个问题在这里已经有答案了 看下面的例子 void Main APPROACH 1 With an anonymous type var myObject new Property1 PropertyValue1 WORKS Propert
  • 如何防止 EMR Spark 步骤重试?

    我有一个 AWS EMR 集群 emr 4 2 0 Spark 1 5 2 我在其中从 aws cli 提交步骤 我的问题是 如果 Spark 应用程序失败 则 YARN 会尝试再次运行该应用程序 在相同的 EMR 步骤下 我怎样才能防止这
  • PHP 日期转换为 strtotime

    我有一个array其中每条记录都有一个 date 场地 日期的格式如下 10 09 2015 当我使用strtotime在这些日期 其中一些结果是false 我认为数据结构中有错误 所以我创建了这个简单的array和一个简单的foreach
  • C++:cin while cout [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 好吧 我正在用 C 编写一个聊天程序 以便在 Linux 终端中使用 我希望在打字时也能收到消息 基本上 非阻塞cin
  • 开源 C/C++ 数学表达式解析器库 [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • file_get_contents(): php_network_getaddresses: getaddrinfo 失败

    我正在尝试使用 cron 作业将一些值从一台服务器更新到另一台服务器 我使用 file get contents 奇怪的是 这偶尔会失败 一分钟还可以 一分钟就不行了 我收到这两个错误 PHP 警告 file get contents ph
  • 升级到 ASP.NET MVC 版本 2

    我今天一直在 ASP NET MVC 项目上做一些工作 我尝试发布该网站 但出现错误 我的托管服务提供商告诉我 这是因为我拥有版本 1 而他们支持版本 2 我怎样才能升级到版本2 两个版本之间的差异是否如此巨大以至于后续版本不支持先前版本
  • GoogleUser 对象没有 grantOfflineAccess 方法?

    我在用谷歌登录 https developers google com identity sign in web reference对我网站上的用户进行身份验证 然后作为单独的步骤请求离线权限 根据文档 GoogleUser对象应该有一个方
  • 用户使用 FOSUserBundle 更新配置文件时忽略密码

    我正在使用 FOSUserBundle 并且正在尝试创建一个允许用户更新其用户个人资料的页面 我面临的问题是 如果用户不想更改 更新密码 我的表单不要求用户重新输入密码 因此 当用户使用空密码提交表单时 数据库将使用空字符串进行更新 并且用
  • .NET Core 中的 Kustos 连接字符串问题

    我想访问 Kusto 数据库 而无需硬编码密码或任何应用程序密钥 它与 NET Framework 完美配合 以下是代码 var serviceName help var authority contoso com Or the AAD t
  • 根据相同的子值 (ID) 合并两个不同的父节点内容 - XSL 转换

    我找不到这个特定的场景 我猜我无法用英语正确描述它 输入 XML 看起来像这样 当然 listOne 和 listTwo 内有多个项目
  • 在 Facebook OG 元标记上使用 Schema.org itemprop

    现在我正在使用itemprop与 Facebook 开放图谱相结合标签如下
  • 有什么方法可以创建 unmemo-monad 吗?

    假设有人编写了一个下棋或解数独的程序 在这种程序中 使用表示游戏状态的树结构是有意义的 这棵树会非常大 几乎是无限的 这本身并不是一个问题 因为 Haskell 支持无限数据结构 一个常见的无限数据结构示例 fibs 0 1 zipWith