当前位置: 首页 > 知识库问答 >
问题:

什么是Haskell中的“修复”?为什么“修复错误”打印无限字符串?为什么“取10美元修复错误”也是如此?

戚承业
2023-03-14

长话短说,我在看西蒙·佩顿·琼斯的演讲,在21:41的时候,他引用了一句话:

我当时正在处理一个bug,很沮丧,在ghci中输入了“修复错误”…

我试过了。

结果:

λ> import Data.Function -- here is fix
λ> fix error
"*** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: *** Exception: and goes on like this towards infinity

一开始我只是想,这个fix到底做了什么?

所以我看了一些类型

λ> :t error
error :: [Char] -> a
λ> :t fix
fix :: (a -> a) -> a

因此

λ> :t fix error
fix error :: [Char]

但很明显,这仍然没有告诉我多少结果。

然而,更奇怪的是,即使是take 10$fix errorlength$take 10$fix error的输出也和上面的一样是一个永不间断的输出(除了后者的输出,length…,缺少首字母)。

我在看什么?

需要明确的是,目前我仍然不太了解关于黑客的文档。并不是说我花了超过3分钟的时间,但我仍然迷失在第一行。

共有2个答案

微生俊名
2023-03-14

它会产生错误(error(error(error…))。因为错误的类型为[Char]-

为什么也拿10$修复错误也一样?

因为它在获取列表的前10个元素时也会出错,因为评估列表会引发错误,并且在打印异常时,将开始相同的行为。

因此,它永远不会生成Chars列表:它会引发一个错误,并开始打印错误消息,而不是返回它。

严成礼
2023-03-14

fix计算函数的固定点;固定点是一个可以提供给函数的值,它将产生与结果完全相同的值。

例如,如果您有函数f_="hello"(或const"hello"),则此函数的固定点是字符串"hello"。事实上修复f"hello"

许多函数都有多个固定点,因此fix的文档需要指定返回哪个固定点。例如:

g :: Integer -> Integer
g x
  | even x = x
  | otherwise = x + 1

每个偶数都是g的固定点,但fix gpromise(按其类型)是一个特定的整数。哪一个?

文档中说,fix产生的固定点最少,并进一步阐明,这意味着输入函数的固定点定义的值最少。请注意,“最小定义”并不是指定义的最小值,而是指具有最小“定义性”的值。在非正式意义上,这是一个技术领域,我并没有像我希望的那样处于最顶端:像1::IntegerTrue只是'a'等完全定义的值,因为您可以在不出错的情况下对它们进行全面评估。底部值(未定义让x=x在x中等)完全未定义。中间是像1:2:undefined这样的值,在这些值中,您可以查看某些结构,而不会遇到错误,但内部某处有一个底部。

因此,fix g只是底部(当我尝试时,GHC检测到一个无限循环并中止了它),因为g undefined是一个错误(所有底部都是“相同的值”)。

事实证明,在使用fix时编写的大多数简单函数都是如此。对于任何严格函数(以任何方式检查其参数的函数),bottom将是一个不动点,这就是fix将要计算的那个。那么我们为什么要关心它呢?

fix在理论上很有意义,因为你可以用它在一种缺乏直接支持的语言中实现递归。在这样的递归定义中:

sum :: [Integer] -> Integer
sum [] = 0
sum (x : xs) = x + sum xs

事实上有一些令人印象深刻的事情正在发生。您正在定义sum,但sum在其自身定义的范围内。实现该功能比编译只使用预先存在的定义的定义要困难一些。让我们想象一下,我们无法做到这一点,但我们仍然希望编写sum。你可以这样做:

sum' :: ([Integer] -> Integer) -> [Integer] -> Integer
sum' _ [] = 0
sum' rec (x : xs) = x + rec xs

sum = fix sum'

现在,每个定义都只使用以前定义过的东西;没有自我参照。与直接调用自身不同,sum'接收一个额外的参数,该参数是它应该在列表尾部调用的函数。该函数参数必须具有我们最初想要给出的sum类型,这使得sum'类型成为a的一个实例-

它这样做的方式是通过生成形式sum'(sum'(sum'(sum'...))的“无限嵌套”表达式(这基本上是它找到任何函数不动点的方式;答案已经变得相当长了,所以我不会在这里详细说明为什么它会起作用)。每个sum'都会收到一个参数,该参数说明如何处理列表的尾部;该参数本身就是对sum'的另一个调用,它需要一个参数说明如何处理原始列表尾部的尾部,该参数是对sum'的另一个调用,依此类推。最终(如果列表是有限的)我们找到了空列表的基本情况,不需要下一级嵌套的sum'调用,因此嵌套表达式没有尽头并不重要!(显然,这在急切评估的语言中不起作用)

事实证明,这是一种通用模式,您可以将直接递归转换为fix的使用。

这么说吧,希望你能明白为什么fix error会这样。Willem Van Onsem的答案在这里很好,所以我不会详细重复。但是基本上,fix error必须产生一个字符串s,这样error s就相当于s。当然,这对于任何非底部字符串都是不可能的,因为error总是产生底部(这就是它的全部意义),所以fix error必须是某种形式的底部。在搜索固定点时,它会生成一个无限嵌套的表达式error(error(error…) ,当GHC打印错误消息时,它本身会生成一个错误,而该错误消息是另一个错误,等等,您看到的是生成的输出。

 类似资料:
  • 问题内容: 作为开发人员,我与E_NOTICE一起工作。不过最近,有人问我为什么应该修复E_NOTICE错误。我能提出的唯一理由是纠正这些问题的最佳实践。 还有其他人有任何理由证明纠正这些问题所花费的额外时间/成本吗? 更具体地说,如果代码已经起作用,为什么经理应该花钱修复这些问题? 问题答案: 摘要 在PHP运行时配置文件给你一些想法,为什么: 在开发过程中启用E_NOTICE有一些好处。 出于

  • 我有一些代码,当我运行它时会产生一个错误,说: NoSuchMethod:对null调用了方法“XYZ” 这意味着什么?我该如何修复它?

  • 为什么字段resultsqueue的修饰符重复?即使当我将resultQueue名称更改为每隔一个名称时,仍然会得到这个错误。当我在main函数中移动resultsQueue时,我不会得到这个错误。 这是我的代码:

  • 问题内容: 我见过人们在HTML元素上应用CSS属性。 他们为什么这样做,并且可以解决什么错误? 问题答案: 这提供了一个内部属性,在Internet Explorer 7及更低版本中被称为。 可以通过给元素“布局”来解决许多Internet Explorer的呈现不一致问题。在本文中,作者重点研究了这一复杂问题的某些方面。 “布局”是IE / Win专有的概念,它确定元素如何绘制和绑定其内容,与

  • 在一个create-react-app typescript项目中,我试图编写这个只是为了快速测试一些东西: 但它给了我以下错误,有一个红色的波浪线: 当提供'-隔离模块'标志时,所有文件都必须是模块。 但是,如果我将文件更改为以下内容,那么一切显然都很好(当然除了未使用的导入): 为什么?这里发生了什么事?< code> - isolatedModules实际上是什么意思/做什么?

  • 我需要将12小时的时间转换为24小时的格式。 我现在已经把12小时的时间硬编码了,以使事情更简单。 我的逻辑:输入sting 07:05:45PM提取最后2个字符。如果AM check为前两个字符,则为12。。如果是,则将其设置为00,否则按原样输出,如果PM检查前两位数字是否为12。。如果是,请保持原样,如果不是,则在前2位加上12 总线错误:10是我运行代码得到的