如何在惰性函数式编程语言中实现调试?

2024-04-04

我想知道如何用惰性函数语言实现调试。
你能使用断点、打印语句和传统技术吗?这是个好主意吗?
据我了解,纯函数式编程不允许有副作用,除了 monad 之外。
执行顺序也无法保证。
您是否必须为要测试的每个代码部分编写一个 monad? 我想从这个领域更有经验的人那里得到一些关于这个问题的见解。


没有什么可以阻止您在延迟评估的函数程序中使用断点。与急切评估的区别是when程序将在断点处停止并且跟踪将是什么样子。当设置断点的表达式实际上被减少时(显然),程序将停止。

您得到的不是您习惯的堆栈跟踪,而是导致带有断点的表达式的减少。

小愚蠢的例子。你有这个 Haskell 程序。

add_two x = 2 + x

times_two x = 2 * x

foo = times_two (add_two 42)

然后你在第一行放置一个断点(add_two),然后评估foo。当程序在断点处停止时,用一种热切的语言,您会期望有一个类似的跟踪

add_two
foo

and times_two甚至还没有开始评估,但在 GHCi 调试器中你会得到

-1  : foo (debug.hs:5:17-26)
-2  : times_two (debug.hs:3:14-18)
-3  : times_two (debug.hs:3:0-18)
-4  : foo (debug.hs:5:6-27)
<end of history>

这是导致您放置断点的表达式减少的减少列表。请注意,它看起来像times_two“叫”foo尽管它没有明确这样做。从这里可以看出评价2 * x in times_two(-2) 确实强制评估(add_two 42)(-1) 从foo线。从那里您可以像在命令式调试器中一样执行一个步骤(执行下一个减少)。

使用 eager 语言进行调试的另一个区别是变量可能尚未被评估 thunk。例如,在上面的跟踪和检查中的步骤-2x,你会发现它仍然是一个未评估的 thunk(在 GHCi 中用括号表示)。

有关更详细的信息和示例(如何单步执行跟踪、检查值……),请参阅GHCi 调试器部分 http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-debugger.html在 GHC 手册中。还有莱克萨IDE http://leksah.org/由于我是 VIM 和终端用户,所以我还没有使用它,但根据手册,它有一个 GHCi 调试器的图形前端。

您还要求打印报表。仅对于纯函数,这不太容易实现,因为 print 语句必须位于 IO monad 内。所以,你有一个纯函数

foo :: Int -> Int

并且希望添加跟踪语句,打印将在 IO monad 中返回一个操作,因此您必须调整要放入​​该跟踪语句的函数的签名以及调用它的函数的签名, ...

这不是一个好主意。因此,您需要某种方法来打破纯度来实现跟踪语句。在 Haskell 中,这可以通过以下方式完成unsafePerformIO。有的是Debug.Trace http://www.haskell.org/ghc/docs/latest/html/libraries/base/Debug-Trace.html已经有功能的模块

trace :: String -> a -> a

它输出字符串并返回第二个参数。不可能将其编写为纯函数(好吧,如果您打算真正输出字符串)。它用unsafePerformIO在引擎盖下。您可以将其放入纯函数中以输出跟踪打印。

您是否必须为要测试的每个代码部分编写一个 monad?

我建议相反,使尽可能多的函数变得纯净(我假设这里你指的是用于打印的 IO monad,monad 不一定是不纯净的)。惰性求值允许您非常干净地将 IO 代码与处理代码分开。

命令式调试技术是否是一个好主意取决于具体情况(像往常一样)。我发现使用 QuickCheck/SmallCheck 进行测试比命令式语言中的单元测试有用得多,因此我会首先采用这条路线,以避免尽可能多的调试。 QuickCheck 属性实际上制定了简洁的函数规范(命令式语言中的许多测试代码对我来说看起来只是另一块代码)。

避免大量调试的一个技巧是将函数分解为许多较小的子函数并测试尽可能多的子函数。当来自命令式编程时,这可能有点不寻常,但无论您使用哪种语言,这都是一个好习惯。

再说一遍,调试!=测试,如果某个地方出了问题,断点和跟踪可能会帮助您。

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

如何在惰性函数式编程语言中实现调试? 的相关文章

  • 如何使用 swift flatMap 从数组中过滤掉选项

    我对 flatMap 有点困惑 添加到 Swift 1 2 假设我有一些可选类型的数组 例如 let possibles Int nil 1 2 3 nil nil 4 5 在 Swift 1 1 中 我会做一个过滤器 然后是一个像这样的地
  • 停止所有 JavaScript 执行

    是否有一个相当于 php die 函数的 javascript 可以停止所有 javascript 包括将来的 ajax 请求回调 超时等 运行 注意 我无法在调试器中使用断点 因为 bug 存在于 ie8 中 并且调试器会阻止您在断点处向
  • 注释扩展函数的惰性求值

    我编写了一个函数来扩展组内的注释 function data group col expand col data gt dplyr group by rlang ensym group col gt dplyr mutate rlang e
  • Eclipse 调试模式下的 GDB 找不到 stdlib/rand.c

    我试图让 gdb 在 ubuntu 上与 eclipse cdt 一起运行 以开始调试一些简单的程序 所以我做了我认为必要的步骤来让它运行 1 创建可执行项目 2 Compile 3 Run 4 创建文件 gdbinit 并将其放在主项目文
  • 无法在 UWP 中调试 .NET Standard 2.0 DLL

    我创建了一个新的 Xamarin Forms 解决方案 升级了所有 NuGet 确保 UWP 版本的目标版本为 16299 并确保 NET Standard 项目的目标版本为 2 0 我运行了该项目并能够很好地调试 NET Standard
  • valgrind 和 iOS SDK 4.2?

    使用 valgrind 运行 iOS 4 2 应用程序时遇到问题 我从 Macports 安装了 valgrind 3 6 0 SVN Xcode 3 2 5 当我修改 main 以运行 valgrind 时 我得到以下输出 Detecte
  • WinDbg中出现“SOS版本与您正在调试的CLR版本不匹配”怎么办?

    我的某些应用程序出现问题 它是一个基于 wcf 的应用程序 在 Windows 2003 Server x86 的 IIS6 下运行 在事件日志中 我从 W3SVC WP 源 EventID 2262 收到这样的错误 ISAPI C WIN
  • ipdb 和 pdb++ 之间的区别?

    Python 有一个名为 pdb 的默认调试器 但社区创建了一些替代品 其中两个是ipdb https github com gotcha ipdb and pdb https github com pdbpp pdbpp 它们似乎迎合了相
  • 当前本地调试 Travis 构建的工作流程是什么?

    One 曾经能够 https stackoverflow com questions 16677232 where can i download the 64 bit travis ci vm images to 下载流浪盒 http re
  • 如何轻松调试布局 Xml 警告/错误?

    我陷入了这个错误 Warning simplexml load string Entity line 46 parser error Comment not terminated in lib Varien Simplexml Config
  • 当我使用nodemon和ts-node时,为什么节点检查器没有启动?

    我有一个用打字稿编写的简单节点服务器 我的 package json 配置为 scripts build tsc dev nodemon watch src e ts json exec ts node src server ts debu
  • 如何调试.NET Windows Service OnStart方法?

    我用 NET 编写的代码仅在作为 Windows 服务安装时才会失败 该故障甚至不允许服务启动 我不知道如何进入 OnStart 方法 如何 调试 Windows 服务应用程序 http msdn microsoft com en us l
  • 我无法在剃刀视图中设置断点

    我知道可以在 MVC Razor 视图中设置断点 但出了点问题 它不再工作了 我尝试重新启动 Visual Studio 2013 并更改调试的一些选项 你有什么建议吗 感谢弗拉基米尔 我能找到解决方案 我必须清理并重建整个解决方案 我之前
  • 在依赖类型的函数式编程语言中,扁平化列表是否更容易?

    在 haskell 中寻找一个可以展平任意深度嵌套列表的函数时 即应用的函数concat递归并在最后一次迭代时停止 使用非嵌套列表 我注意到这需要有一个更灵活的类型系统 因为随着列表深度的变化 输入类型也会变化 确实 有几个 stackov
  • Xcode“使用性能工具运行”被禁用?

    我正在尝试从我的 Xcode 项目中查找内存泄漏 我不知道发生了什么 我无法选择任何内容Run gt Run with performance tool 事物列表被禁用 请帮助我 我是初学者 问题是我已经删除了构建文件夹并尝试使用性能工具运
  • 如何调试 numpy 掩码

    这个问题与this one https stackoverflow com q 73672739 11004423 我有一个正在尝试矢量化的函数 这是原来的函数 def aspect good angle float planet1 goo
  • Haskell 中列表列表的笛卡尔积

    给定一个长度列表的列表x所有子列表的长度都相同y 输出y x长度列表x包含每个子列表中的一项 例子 x 3 y 2 1 2 3 4 5 6 Output 2 3 8不同的输出 1 3 5 1 4 5 1 3 6 1 4 6 2 3 5 2
  • GDB单步汇编并显示下一条将要执行的指令。 [复制]

    这个问题在这里已经有答案了 使用 gdb 调试器可以执行什么命令来单步执行并显示将要执行的下一条指令 我熟悉windbg这个操作非常简单 例如 我有以下函数 当我通过以下方式进入代码时si我想显示将要执行的下一条指令 而无需通过反汇编进行完
  • Vim 脚本中的“reduce”函数

    Vim 脚本有一些非常基本的函数式编程工具 It has map and filter 但据我所知它缺乏reduce 功能 Reduce https en wikipedia org wiki Fold 28higher order fun
  • “功能性”Rust 对性能有哪些影响?

    我正在关注 Rust 轨道运动 io https exercism io 我有相当多的 C C 经验 我喜欢 Rust 的 功能 元素 但我担心相对性能 我解决了 行程编码 问题 https exercism io tracks rust

随机推荐

  • 集合接口和WCF

    我正在使用 C 和 WCF 来做 Web 服务 我有一个实现 IEnumerable 的类的成员变量 我尝试通过执行以下操作将其序列化为我的数据合同的一部分 DataContract class Item DataMember privat
  • 约束消失的情况:更高等级类型的怪异

    下面描述的所有实验都是使用 GHC 8 0 1 完成的 这个问题是后续问题具有类型别名混淆的 RankNTypes https stackoverflow com q 40252867 2751851 那里的问题归结为像这样的函数类型 LA
  • 获取 i18next 翻译器 缺少密钥

    这是我第一次使用 i18next 我不知道如何让它发挥作用 这似乎是文档 http i18next com docs 对我来说是不完整的 这是我使用 i18next 的 HTML 代码
  • JDBC无法在openshift上连接mysql数据库

    我设法使用 phpMyAdmin 等在 OpenShift 上设置 MySQL 数据库 我被告知我的数据库的主机名和端口分别是 OPENSHIFT MYSQL DB HOST 和 OPENSHIFT MYSQL DB PORT 我将其放入
  • 多次借用的借用错误

    我正在 Rust 中实现一个就地递归解析器 但遇到了一些借用错误 代码片段重现了问题 尽管它不是很有用 use std vec Vec struct MyBorrows lt a gt val a mut i32 impl lt a gt
  • com.fasterxml.jackson.databind.exc.InvalidTypeIdException:无法将类型 id '[' 解析为子类型

    我有一个名为 Fruit 的抽象类 我把 JsonTypeInfo and JsonSubTypes其如下 JsonTypeInfo use JsonTypeInfo Id NAME include JsonTypeInfo As PROP
  • 如何让ListView在转换到另一个路线时保留其滚动?

    我想在我的颤动应用程序中完成滑动到右侧的转换 问题是路线转换有点创建我想要从中转换的页面的新实例 所以ListView滚动重置 看视频 https youtu be PdLhyvNoU8 这就是我创建新路线的方式 oldRoute need
  • dompdf 图像不是真实图像,无法读取或为空

    我在使用 dompdf 时遇到问题 我插入的图像在转换为 pdf 文件时无法读取 当我使用将其加载到 dompdf 时 php方法 img src gt 我得到一个带有 X 的方框缩略图 它说 图像不是真实图像 不可读或为空 用文本打印我的
  • Nodejs JOIN 查询:格式化 JSON 输出

    我正在制作一个非常简单的 RIGHT JOIN 查询 但我无法正确格式化输出 这是查询 connection query sql SELECT users rides FROM users RIGHT JOIN rides ON users
  • 需要帮助 Discord 机器人队列

    我一直在尝试为不和谐机器人和我的 gt q命令基本上工作为join play queue同时 问题是它只能同时对 2 首歌曲进行排队 所以我需要帮助使其对多首歌曲进行排队 queues check queue def check queue
  • 重复 data.frame 的每一行列中指定的次数

    df lt data frame var1 c a b c var2 c d e f freq 1 3 扩展上面 data frame 的每行前两列 以便每行重复 freq 列中指定的次数 最简单的方法是什么 换句话说 从这里开始 df v
  • 如何将 Twitter 配置移出控制器? (导轨)

    我正在使用推特宝石 https github com sferik twitter通过斯费里克 我认为在控制器中存储我的 Twitter 应用程序的配置非常混乱 class HomeController lt ApplicationCont
  • 如何使用`[[`和`$`作为函数?

    我知道我可以这样做 x lt list a 1 b 1 y lt list a 1 JSON lt rep list x y 10000 sapply JSON a 然而 我在使用时遇到了困难 以同样的方式 sapply JSON a sa
  • 如何使用列表理解来模拟 sum()?

    是否可以使用 sum 来模拟类似的东西列表理解 http en wikipedia org wiki List comprehension Python 例如 我需要计算列表中所有元素的乘积 list 1 2 3 product magic
  • 发送多个请求时如何将结果与请求匹配?

    总结 正如其标题所示 Guzzle 允许一次发送多个请求以节省时间 如下所示文档 http docs guzzlephp org en latest http client client html sending requests resp
  • Google 地图静态 API 返回奇怪的图像

    我有一个页面 其静态地图 URI 的形式为 当我从任何浏览器访问此页面时 它显示得很好 但当我通过通过我们的 BES 连接的黑莓使用它时 但相同的无线网络 然后出现这个图像 有谁知道这张图是什么意思 你有超出使用限制 http code g
  • 如何获取自定义错误页面(Tomcat)中的消息?

    在 JSP 中 您可以使用response sendError int code String message 返回特定的错误代码 例如 404 表示未找到 和消息 只要您使用默认的丑陋的 Tomcat 错误页面 这些消息就可以正常显示 但
  • Javascript 在 window.open 之后调用函数

    我试图在 window open 函数完全加载后调用一个函数 然而 使用 onload 函数调用得太早了 所点击的 URL 将打开一个 Excel 电子表格 下载可能需要 2 秒到 1 分钟 一旦 window open 函数被调用 onl
  • MvvmCross iOS:如何绑定MapView Annotation跳转到另一个视图?

    当单击标注附件按钮时 如何绑定 MapView 的注释以切换到不同的视图 如何实现注释的 CalloutAccessoryControlTapped 方法 或者最好的方法是什么 这是我的代码 Register MapView public
  • 如何在惰性函数式编程语言中实现调试?

    我想知道如何用惰性函数语言实现调试 你能使用断点 打印语句和传统技术吗 这是个好主意吗 据我了解 纯函数式编程不允许有副作用 除了 monad 之外 执行顺序也无法保证 您是否必须为要测试的每个代码部分编写一个 monad 我想从这个领域更