0

我对 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这里使用 a 。

4

3 回答 3

1

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

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

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

你可以做很多事情来减少内存使用,递归只是重新实现一个折叠,但这让你知道如何一次计算答案。

于 2019-10-16T12:09:25.360 回答
0

像这样定义一个辅助内部函数:

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]它不是一个数组——它是一个整数列表

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

于 2019-10-15T23:27:19.667 回答
0

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

arrayFunc :: (Integral a) => [a] -> a
arrayFunc ls
    | n == 0     = 1
    | even n     = (sum ls) `div` (fromIntegral n)
    | otherwise  = product ls
    where
    n     = length xs 
于 2019-10-16T09:53:58.837 回答