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

What is the syntax for different recursions depending on two boolean guards?

我是 Haskell 的新手,我正在尝试编写一个简单的函数,它将一个整数数组作为输入,然后 return 所有元素的乘积或平均值,分别取决于数组的长度是奇数还是偶数。

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

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 :: [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] 不是一个数组——它是一个 list 整数。

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

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

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

你有警卫的原因是因为你试图在你实际查看列表中的值之前确定列表的长度。

与其进行多次传递(一次计算长度,另一次计算和或乘积),只需计算 所有 您可能 需要,当你遍历列表时,然后在最后做出决定并 return 适当的值:

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

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