繁体   English   中英

无法理解haskell中的原始递归定义

[英]Can't get my head around primitive recursion definitions in haskell

我已经很好地了解了原始递归定义是什么,但是我似乎仍然无法理解它。

例如,我似乎无法向自己解释如何执行以下操作(但我似乎能够这样做):

行使:

定义函数productIt :: [Int] -> Int ,它给出整数列表的乘积,并为空列表返回1; 为什么选择此特定值作为空列表的结果?

我(当然)提出了解决方案:

productIt :: [Int] -> Int
productIt [] = 1
productIt (x:xs) = x * productIt xs

这对于练习中的问题非常有效。 然而,我似乎仍然难以绕过最后一行。

关于如何思考这一点的任何想法都将受到最高的赞赏。

在英语中,您可以将最后一行读作:

数字列表的乘积是第一个数字乘以其余数字的乘积。 如果没有数字,那么我们只说产品是1。

像这样将它转换为英语通常可以帮助我理解递归函数的工作原理和原因。 您也可以使用头脑中的Haskell解释器来评估它:

  productIt [2,3,4]
= 2 * (productIt [3,4])
= 2 * (3 * (productIt [4]))
= 2 * (3 * (4 * (productIt [])))
= 2 * (3 * (4 * (1)))
= 2 * (3 * (4))
= 2 * (12)
= 24

你使用1作为普通案例[]的原因是因为当你乘以它时它不会改变结果。

productIt (x:xs) = x * productIt xs

例如,假设您将其定义为:

productIt [] = 2                      -- line 1
productIt (x:xs) = x * productIt xs   -- line 2

然后考虑:

productIt [1] = productIt (1:[])
              = 1 * productIt []    -- by line 2
              = 1 * 2               -- by line 1
              = 2                   -- WRONG!!!

你正在寻找整数列表的乘积,对于[1],答案应该是1。

在我解释最后一行代码之前,让我总结一下解决这类问题的过程。 有两个关键问题:

  1. 什么是最简单的案例?
  2. 我可以用下一个最简单的解决方案来表达解决方案吗?

好的,所以我们想编写一个函数来计算列表中所有数字的乘积。

问题1:最简单的情况是没有任何数字。 如果这是我第一次遇到这个问题,对我来说可能不是很明显,在这种情况下答案应该是什么,但让我们暂时把它放在一边。

问题2:如果我有一个列表[n0,n1,n2,... nk],并且我知道除了第一个数字之外的所有数字的产品(我们称之为p),那么答案是第一个元素时间该产品,或n0 * p。

第一行代码将处理琐碎的案例:

productIt [] = 1

这表示空列表参数[]的函数productIt的值为1.(我在上面解释了为什么答案必须为1.)这样可以解决这个小问题。 现在我们需要在列表不为空的情况下定义productIt。 让我们看看最后一行代码:

productIt (x:xs) = ... something?

左侧使用模式匹配。 模式(x:xs)将匹配具有一个或多个元素的列表。 当该表达式匹配时,它将x绑定到第一个元素,将xs绑定到列表的其余部分。 因此,我们不仅匹配模式,我们将x和xs定义为奖励。 这就是使模式匹配在Haskell中非常强大的原因。

因此,如果列表的第一个元素是x,列表的其余部分(除第一个元素之外的所有元素)都是xs,那么答案是什么? 我们已经确定它是所有剩余元素(xs)的乘积的第一个元素(x)。 所以...

productIt (x:xs) = x * productIt xs

此外,yjerem为您提供了Haskell如何评估它的出色解释。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM