首页 > 解决方案 > Haskell:具有长度,总和,列表平方和的累加器

问题描述

我是 Haskell 的新手,正在尝试使用累加器实现一个函数,但不知道如何正确使用它。

这是一个使用数字列表的函数,并使用内置函数返回具有长度、总和和平方和的三元组 (Int, Int, Int):

stats1 :: [Int] -> (Int,Int,Int)
stats1 xs = (length xs, sum xs, sumsq xs)

sumsq :: [Int] -> Int
sumsq [] = 0
sumsq (x:xs) = (^2) x + sumsq xs

但是,当我尝试使用累加器方式时:

stats2 :: [Int] -> (Int,Int,Int)
stats2 [] = (0,0,0)
stats2 (x:xs) = (len+1, acc+x, sumsquare + x*x ) (stats2 xs)
  where len = 0
        acc  = 0
        sumsquare = 0

我收到错误消息:

Couldn't match expected type ‘(Int, Int, Int) -> (Int, Int, Int)’
                with actual type ‘(Integer, Int, Int)’
    The function ‘(len + 1, acc + x, sumsquare + x * x)’
    is applied to one argument,
    but its type ‘(Integer, Int, Int)’ has none
    In the expression:
      (len + 1, acc + x, sumsquare + x * x) (stats2 xs)
    In an equation for ‘stats2’:
        stats2 (x : xs)
          = (len + 1, acc + x, sumsquare + x * x) (stats2 xs)
          where
              len = 0
              acc = 0
              sumsquare = 0

我怎样才能通过stats1使用蓄电池来实现相同的目标?谢谢。

标签: haskellaccumulator

解决方案


要使用这种累加器传递样式,您首先需要声明一个递归函数,该函数采用额外的累加参数。这可以在where子句中完成,在我的示例中使用recurse. 在 的初始调用中recurse,元组被初始化为(0,0,0)。在每一步( 的第二个模式recurse)中,值被累加,并且基本情况( 的第一个模式recurse)返回结果元组。

stats2 :: [Int] -> (Int,Int,Int)
stats2 l = recurse l (0,0,0) where
        recurse [] tuple = tuple
        recurse (x:xs) (lenr,sumr,sumsq) = recurse xs (lenr+1, sumr+x, sumsq + x*x )

致电:

> stats3 [1,2,3]
(3,6,14)

您尝试的问题是您尝试stats2使用元组作为附加参数进行递归调用,但您将其转过来,以便元组是该构造中的实际函数(它不接受任何参数,因此出现错误消息)。此外,如果这可行,则这些值将在每一步基本情况中用零初始化。


推荐阅读