我应该避免使用 Monad 失败吗?

2024-04-04

我对 Haskell 相当陌生,并且慢慢地意识到 Monad failure 的存在有问题。现实世界哈斯克尔警告不要使用它 http://book.realworldhaskell.org/read/monad-transformers.html#x_Et(“我们再次建议您几乎总是避免使用失败!”)。我今天才注意到罗斯帕特森称其为“疣,而不是设计模式”早在2008年 http://haskell.1045720.n5.nabble.com/Proposal-Add-Text-Read-maybeRead-Read-a-gt-String-gt-Maybe-a-td3174167.html(并且似乎在那条线索中达成了相当多的一致)。

在观看 Ralf Lämmel 博士的表演时谈谈函数式编程的本质 http://channel9.msdn.com/Shows/Going+Deep/C9-Lectures-Dr-Ralf-Lmmel-AFP-The-Quick-Essence-of-Functional-Programming,我开始理解可能导致 Monad 失败的紧张局势。在讲座中,Ralf 谈到了向基本单子解析器添加各种单子效果(日志记录、状态等)。许多效果需要更改基本解析器,有时还需要更改所使用的数据类型。我认为向所有单子添加“失败”可能是一种妥协,因为“失败”非常常见,并且您希望尽可能避免对“基本”解析器(或其他)进行更改。当然,某种“失败”对于解析器来说是有意义的,但并不总是如此,例如 State 的 put/get 或 Reader 的 Ask/local。

让我知道我是否走错了路。

我应该避免使用 Monad 失败吗? Monad 失败的替代方案是什么? 是否有任何不包含此“设计疣”的替代 monad 库? 我在哪里可以了解有关此设计决策的历史的更多信息?


一些 monad 具有合理的故障机制,例如终端单子:

data Fail x = Fail

有些 monad 没有合理的故障机制(undefined是不明智的),例如初始单子:

data Return x = Return x

从这个意义上说,要求所有单子都具有一个明显的缺陷fail方法。如果您正在编写对 monad 进行抽象的程序(Monad m) =>,使用这个泛型并不是很健康m's fail方法。这将产生一个可以用 monad 实例化的函数,其中fail不应该真正存在。

我发现反对使用的人较少fail(特别是间接地,通过匹配Pat <- computation)当在一个特定的单子中工作时,一个好的fail行为已被明确规定。这样的程序有望在回归旧规则的情况下继续存在,在旧规则中,非平凡的模式匹配创造了对MonadZero而不是仅仅Monad.

有人可能会说,更好的纪律总是明确地处理失败案例。我反对这个立场有两个原因:(1)一元编程的目的是避免这种混乱,(2)当前对一元计算结果进行案例分析的表示法非常糟糕。 SHE 的下一个版本将支持该表示法(也见于其他变体)

case <- computation of
  Pat_1 -> computation_1
  ...
  Pat_n -> computation_n

这可能会有所帮助。

但这整个情况真是一团糟。通过单子支持的操作来表征单子通常很有帮助。你可以看到fail, throw等作为一些单子支持的操作,但其他单子不支持。 Haskell 使得支持可用操作集中的小型局部更改变得非常笨拙和昂贵,通过解释如何根据旧操作来处理新操作来引入新操作。如果我们真的想在这里做得更整洁,我们需要重新考虑如何catch作品,使其成为之间的翻译不同的本地错误处理机制。我经常想将可能在无信息的情况下失败的计算(例如,通过模式匹配失败)与一个处理程序括起来,该处理程序在传递错误之前添加更多上下文信息。我不禁感到有时这样做比应有的更困难。

所以,这是一个可以做得更好的问题,但至少,使用fail仅适用于提供合理实现并正确处理“异常”的特定单子。

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

我应该避免使用 Monad 失败吗? 的相关文章

  • 生成所有可能的树

    给定以下数据类型定义 data FormTree Empty Node FormTree FormTree deriving Show 我想编写一个函数 它生成一个无限列表 其中包含按长度排序的所有可能的树 例如节点数量 下面的代码几乎满足
  • 将系统命令的结果绑定到 Haskell 中的变量

    如何在 Haskell 中运行系统命令and将其结果 即标准输出 绑定到变量 在伪 Haskell 中 我正在寻找类似以下内容的内容 import System Process main do output lt callCommand e
  • Haskell 中的前提条件检查有哪些选项

    这是一个简单的问题 我认为答案很复杂 一个非常常见的编程问题是函数返回某些内容 或者前置条件检查失败 在Java中 我会使用一些抛出异常的断言函数IllegalArgumentException在方法的开头 如下所示 method body
  • Haskell 中的实例声明

    我有这两个功能 primes sieve 2 where sieve p xs p sieve x x lt xs x mod p gt 0 isPrime number number 1 null x x lt takeWhile x g
  • 如何手动推断表达式的类型

    给定 Haskell 函数 head filter fst 现在的问题是如何手动 手动 找到类型 如果我让 Haskell 告诉我我得到的类型 head filter fst Bool b gt Bool b 但我想了解仅使用所用函数的签名
  • 将数据类型设置为 Kind * -> * 这不是函子

    布伦特 约尔吉类型分类百科全书 https www haskell org haskellwiki Typeclassopedia给出以下练习 举一个类型的例子 gt 不能将其制成 的实例Functor 不使用undefined 请告诉我什
  • 将 num 的签名键入 double?

    我才刚刚开始为你学习 Haskell 以获得伟大的好处 并且我在类型类方面遇到了一些麻烦 我想创建一个接受任何数字类型并强制其为双精度的函数 我的第一个想法是定义 numToDouble Num gt Double 但我认为这不起作用 因为
  • 将两个 Int 值相除以获得 Float 的正确方法是什么?

    我想分两份IntHaskell 中的值并获得结果Float 我尝试这样做 foo Int gt Int gt Float foo a b fromRational a b 但 GHC 版本 6 12 1 告诉我 无法将预期类型 Intege
  • Haskell 泛化问题(涉及列表理解)

    假设我想知道a上的所有要点 x y 矩形内的平面has 我可以使用列表推导式来计算 如下所示 let myFun2D x y x lt 0 2 y lt 0 2 现在 如果我想为一个人完成同样的事情 x y z 空间 我可以采取同样的方式并
  • 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
  • Haskell 入门

    这个问题的答案是社区努力 help privileges edit community wiki 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 几天来 我一直试图理解 Haskell 中的函数式编程范例 我通过阅读教程和观看截屏视频
  • 标准的能力

    我发现了一些使用标准的旧例子here http www serpentine com blog 2009 09 29 criterion a new benchmarking library for haskell 看起来好像早在 2009
  • Haskell 中的尾递归字符串分割

    我正在考虑分割字符串的问题s在一个字符处c 这表示为 break c s 其中 Haskell 库定义break c 足够接近 br br s h t if c h then s else let h t br t in h h t 假设我
  • Traversable 类型类的用途

    有人可以向我解释一下类型类的目的是什么吗Traversable 类型类定义是 class Functor t Foldable t gt Traversable t gt where So Traversable is a Functor
  • 如何在haskell中获取变量名称

    我来到 haskell 时有一些 c 背景知识 想知道是否有类似的 define print a printf s d n a a int a 5 print a 应该打印 a 5 这是 augustss 提到的 TH 解决方案 LANGU
  • Haskell:IORef 的性能

    我一直在尝试在 Haskell 中编码一个需要使用大量可变引用的算法 但与纯粹的惰性代码相比 它 也许并不奇怪 非常慢 考虑一个非常简单的例子 module Main where import Data IORef import Contr
  • 在 monad 转换器类型类中使用列表 monad?

    我的目标是创建一个在 ReaderT WriterT 堆栈或 RWS 堆栈中使用列表 monad 的函数 更一般地说 如何在 mtl 类型类 例如 MonadReader MonadWriter 中使用列表 monad 我为什么要尝试这样做
  • Haskell 标准库是什么?

    GHC专用库可以称为标准库吗 或者只有 Haskell 2010 报告中的那些才算数 许多 GHC 库可以通过 Haskell 报告中的函数来实现 可能与 C 绑定相结合 但其他语言依赖于 GHC 特定的扩展 因为语言报告中定义的当前 Ha
  • 在 Haskell 中合并两个列表

    无法弄清楚如何合并两个列表通过以下方式在哈斯克尔 INPUT 1 2 3 4 5 11 12 13 14 OUTPUT 1 11 2 12 3 13 4 14 5 我想提出一个更懒的合并版本 merge ys ys merge x xs y
  • 如何打乱列表?

    如何从一组数字 1 2 3 直到我击中x 我的计划是重新调整列表 1 2 3 并把它砍在x chopAt 3 2 3 1 2 3 chopAt 3 2 1 3 2 1 3 chopAt 3 3 1 2 3 chopAt chopAt x y

随机推荐

  • 让 JAXB 走得更快

    我有一个 8 兆文件 使用 JAXB 编组需要 1082 毫秒 使用 DOM 需要 862 毫秒 使用 SAX 需要 438 毫秒 这是使用 JDK 1 6 的所有默认设置 没有使用额外的配置 例如使用 woodstox 为了从 JAXB
  • 如何在不弄乱 DataContext 的情况下为 WPF 工具提示设置 PlacementTarget?

    我有一个典型的 MVVM 设置 其中包含 Listbox 和 vm DataTemplate 以及 item vm 数据模板具有工具提示 其中包含绑定到项目虚拟机的元素 一切都很好 现在 我想让工具提示相对于列表框本身放置 它相当大 当鼠标
  • 以 4 为底的二进制 [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如何将数字从二进制转换为基数 4wi
  • HTML 表格中每 n 个单元格创建新行

    我有以下代码 for i 0 i
  • java.lang.IllegalStateException:不支持在启动上下文后添加新的输入、转换和输出操作

    当我尝试在 Spark 的函数调用中创建 dStream 时 出现以下异常 我的通话方法 Override public JavaRDD call JavaRDD v1 throws Exception Queue
  • 后台加载图片,优化ios加载

    我正在尝试优化应用程序中的负载 事实上 我的应用程序中加载了很多图像 并且我花了很多时间等待视图控制器打开 特别是第一个初始视图 其中包含很多图像的图像 我看了一下苹果样品 https developer apple com library
  • Google Mock:为什么NiceMock不忽略意外调用?

    我正在使用 Google Mock 1 7 0 和 Google Test 1 7 0 问题是 当我使用 NiceMock 时 由于意外的模拟函数调用 根据 Google Mock 文档 NiceMock 应忽略该函数 导致测试失败 代码如
  • 按位相等

    我需要在两个字节之间执行按位相等 这意味着 例如 如果我有两个字节 00011011 和 00011110 结果是 11111010 我看到的唯一快速方法是使用以下语句 byte a b set input bytes byte c a b
  • 鼠标移出事件的问题

    我正在使用 JavaScript 隐藏图像并显示隐藏在其下方的一些文本 但是 当您滚动显示文本时 它会触发容器上的 mouseout 事件 然后隐藏文本并再次显示图像 然后它就会进入一个奇怪的循环 html 看起来像这样 div div d
  • 如何在factory_girl中建立/创建多对多关联?

    我有一个Person与具有多对多关系的模型Email模型 我想创建一个工厂 让我为该人生成名字和姓氏 这已经完成 并创建一个基于该人姓名的电子邮件地址 这是我要创建的person s name Factory sequence first
  • 如何在 Xamarin Forms 中处理/取消后退导航

    我尝试通过覆盖来使用后退导航OnBackButtonPressed 但不知怎的 它根本没有被调用 我正在使用ContentPage以及最新的 1 4 2 版本 好吧 经过几个小时我终于弄清楚了 它分为三个部分 1 处理 Android 上的
  • glBufferSubData什么时候返回? [复制]

    这个问题在这里已经有答案了 我想将一个非常大的内存块的内容传输到足够大的 GPU 缓冲区 然后立即更改 CPU 上的内存内容 伪代码是这样的 glBindBuffer very large buffer glBufferSubData ve
  • 两个字典(键和值)的递归差异?

    所以我有一个Python字典 称之为d1 以及该词典稍后的一个版本 称之为d2 我想找到之间的所有变化d1 and d2 换句话说 添加 删除或更改的所有内容 棘手的一点是 值可以是整数 字符串 列表或字典 因此它需要是递归的 这是我到目前
  • android Activity 生命周期中 oncreateoptionsmenu() 的调用顺序是什么?

    Is onCreateOptionsMenu 在之前或之后调用的操作栏onStart 的活动 首先调用 onStart 我尝试将日志消息放入方法中
  • 如何清除

    我知道这是非常基本的 但它让我感到困惑 我有一个基本清单 ul li a href Insert Link Here a li li a href Insert Link Here a li li a href Insert Link He
  • Firebase 持久性 - onDisconnect 与多个浏览器窗口

    我们正在编写一个监控在线状态的应用程序 在多种情况下 我们需要用户打开多个浏览器窗口 我们遇到了一个问题 用户在辅助浏览器窗口中打开并运行 firebase js 代码后 将关闭该辅助窗口 这会将它们在主窗口中的存在设置为脱机 因为 onD
  • .attachClickHandler() 在页面刷新/重定向时不起作用

    我正在尝试在index html 中实现一个自定义的谷歌登录按钮 该按钮在页面加载时完美运行 但在页面重新加载或从另一个页面重定向时则不起作用 页面加载时 控制台语句 1 2 和 3 会自动按顺序打印 4 会在登录时打印 当从另一个页面重定
  • 如何在同构或SSR应用程序中使用MongoDB Stitch Auth?

    想要在 NextJS 应用程序中使用 Stitch 基本上是同构反应 通常 您可以在初始请求的标头中传递 JWT 或会话令牌 如果用户已有会话 您可以立即加载其所有数据并在服务器上合并应用程序 使用 Google Firebase Auth
  • Jenkins 故障 Java 12 OpenJDK - JAVA_HOME 环境变量未正确定义

    配置 Jenkins 2 121 3 使用JDK 12 https download java net java GA jdk12 GPL openjdk 12 linux x64 bin tar gz在 全局工具配置 gt JDK 安装
  • 我应该避免使用 Monad 失败吗?

    我对 Haskell 相当陌生 并且慢慢地意识到 Monad failure 的存在有问题 现实世界哈斯克尔警告不要使用它 http book realworldhaskell org read monad transformers htm