取决于两个布尔守卫的不同递归的语法是什么?



我对Haskell很陌生,正在尝试编写一个简单的函数,该函数将整数数组作为输入,然后返回所有元素的乘积或平均值,具体取决于数组分别是奇数还是偶数长度。

我了解如何为递归设置基本案例,以及如何为不同的情况设置布尔守卫,但我不明白如何协同执行这些操作。

arrayFunc :: [Integer] -> Integer                                                                                       
arrayFunc [] = 1                                                                                                        
arrayFunc array                                                                                                           
| (length array) % 2 == 1 = arrayFunc (x:xs) = x * arrayFunc xs                                                     
| (length array) % 2 == 0 = ((arrayFunc (x:xs) = x + arrayFunc xs) - 1) `div` length xs 

目前我收到错误

"parse error on input '='
Perhaps you need a 'let' in a 'do' block?"

但我不明白我如何在这里使用let

您之所以有守卫,是因为您尝试在实际查看列表中的值之前确定列表的长度。

与其进行多次传递(一次用于计算长度,另一次用于计算总和或乘积(,不如在浏览列表时计算您可能需要的所有值,然后在最后做出决定并返回适当的值:

arrayFunc = go (0, 1, 0, True)
where go (s, p, len, parity) [] = 
if parity  then  (if len /= 0 then s `div` len else 0) 
else  p
go (s, p, len, parity) (x:xs) = 
go (s + x, p * x, len + 1, not parity) xs

您可以采取多种措施来减少内存使用量,递归只是重新实现一个折叠,但这可以让您了解如何一次性计算答案。

定义一个辅助内部函数,如下所示:

arrayFunc :: [Integer] -> Integer
arrayFunc [] = 1
arrayFunc array
| (length array) % 2 == 1  =  go1 array
| (length array) % 2 == 0  =  go2 array
where
go1 (x:xs)  =  x * go1 xs
go2 (x:xs)  =  ((x + go2 xs) - 1) `div` length xs 

这仅涉及您问题中的语法问题。特别是,[Integer]不是一个数组 - 它是一个整数列表

但当然,变量的名称不会影响代码的正确性。

如果不关注递归,这应该是一个可接受的解决方案:

arrayFunc :: (Integral a) => [a] -> a
arrayFunc ls
| n == 0     = 1
| even n     = (sum ls) `div` (fromIntegral n)
| otherwise  = product ls
where
n     = length xs 

相关内容

  • 没有找到相关文章

最新更新