我需要以两种方式编写函数product
:
这样函数就会返回m到n的乘积。
示例:
product 3 5
返回3 * 4 * 5 = 60
由于
答案 0 :(得分:8)
这听起来像是一个家庭作业问题,所以不要只是删掉你的代码,让我们解决这个问题:
输入签名
Haskell是一种具有强类型的函数式语言,因此最好从编写函数的类型签名开始。您的示例显示了两个整数参数和一个整数返回值。我们将其编码为:
product :: Int->Int->Int
这读作“product
是一个需要两个Int
并返回Int
的函数。” (还有其他更正确的方法来阅读这个,但那是另一天)
<强>递归强>
我们将在Haskell中使用一个通用模式。因为在这种情况下我们需要跟踪中间值,所以我们将编写第二个函数product'
,它将采用额外的参数,即正在运行的产品。
product' :: Int->Int->Int->Int
product' accumulator current final = product' (accumulator*current) (current+1) final
在每次迭代时,这将采用最近的累计值乘以当前值并将其作为新累加器传递,它将获取当前值并将其作为新电流加1,并将最终传递给最终值。为了开始,我们编写了我们的原始函数:
product i f = product' 1 i f
或无分数符号
product = product' 1
问题是product'
代码将永远循环。我们需要一种方法来阻止我们当前的流量大于最终目标。
警卫
而不是重写关于警卫模式的书send you to the book。简而言之,在你做某事之前,他们会给你一个布尔值。我们将使用它们来阻止我们的递归。
product' :: Int->Int->Int->Int
product' accumulator current final
| current <= final = product' (accumulator*current) (current+1) final
| otherwise = accumulator
只要current
小于或等于final
,一旦不是最终答案在累加器中,我们会继续递归。
如果 - 则 - 否则强>
警卫可以用机械方式替换为if
构造(可能深度嵌套)。
product' :: Int->Int->Int->Int
product' accumulator current final =
if current <= final
then product' (accumulator*current) (current+1) final
else accumulator
最后的想法
不要写这样的代码。有许多wonderfully generic higher level function只做这些类型的事情。这是编写产品的更好方法:
product i f = foldl (*) 1 [i..f]