Haskell: 具有长度、求和、列表平方和的累加器
Haskell: accumulator with length, summation, summation of square of a list
我是 Haskell 的新手,正在尝试使用累加器实现一个功能,但不知道如何正确使用它。
这是一个使用数字列表的函数,return 一个三元组(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
相同的目标?谢谢。
要使用这种传递累加器的样式,您首先需要声明一个采用额外累加参数的递归函数。这可以在 where
子句中完成,在我的示例中使用 recurse
。在 recurse
的初始调用中,元组用 (0,0,0)
初始化。在每一步(recurse
的第二个模式)中,值被累加,基本情况(recurse
的第一个模式)returns 结果元组。
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
,但您将其翻转过来,因此元组是该构造中的实际函数(需要没有参数,因此出现错误消息)。此外,如果这行得通,则在每个步骤 和 基本情况下,这些值将被初始化为零。
累加器是必须传递给函数的变量。
stats_h :: (Int, Int, Int) -> [Int] -> (Int, Int, Int)
stats_h p [] = p
stats_h (len, sum, sumsq) (x:xs) =
stats_h (len+1, sum + x, sumsq + x*x) xs
stats :: [Int] -> (Int, Int, Int)
stats = stats_h (0, 0, 0)
λ stats_h (0, 0, 0) [1, 2, 3]
(3,6,14)
λ stats [1, 2, 3]
(3,6,14)
我是 Haskell 的新手,正在尝试使用累加器实现一个功能,但不知道如何正确使用它。
这是一个使用数字列表的函数,return 一个三元组(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
相同的目标?谢谢。
要使用这种传递累加器的样式,您首先需要声明一个采用额外累加参数的递归函数。这可以在 where
子句中完成,在我的示例中使用 recurse
。在 recurse
的初始调用中,元组用 (0,0,0)
初始化。在每一步(recurse
的第二个模式)中,值被累加,基本情况(recurse
的第一个模式)returns 结果元组。
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
,但您将其翻转过来,因此元组是该构造中的实际函数(需要没有参数,因此出现错误消息)。此外,如果这行得通,则在每个步骤 和 基本情况下,这些值将被初始化为零。
累加器是必须传递给函数的变量。
stats_h :: (Int, Int, Int) -> [Int] -> (Int, Int, Int)
stats_h p [] = p
stats_h (len, sum, sumsq) (x:xs) =
stats_h (len+1, sum + x, sumsq + x*x) xs
stats :: [Int] -> (Int, Int, Int)
stats = stats_h (0, 0, 0)
λ stats_h (0, 0, 0) [1, 2, 3]
(3,6,14)
λ stats [1, 2, 3]
(3,6,14)