Haskell:记住列表中的前一个元素

Haskell:记住列表中的前一个元素,haskell,scope,Haskell,Scope,简单的问题,不知道怎么做 我正在从Data.List编写一个更有限版本的sum函数,代码如下: -- Sum the contents of a list sum' :: Num a => [a] -> a sum' [] = 0 sum' (x:xs) = x + sum' rest where rest = drop (succ (elemIndex x xs)) xs 我相信,如果elemIndex的x参数在当前列表元素的范围内,这将起作用

简单的问题,不知道怎么做

我正在从Data.List编写一个更有限版本的sum函数,代码如下:

-- Sum the contents of a list

sum' :: Num a => [a] -> a

sum' [] = 0

sum' (x:xs) = x + sum' rest where
              rest = drop (succ (elemIndex x xs)) xs 
我相信,如果elemIndex的x参数在当前列表元素的范围内,这将起作用


我希望尽可能不使用折叠式,因为这是Graham Hutton在Haskell的编程中的一个问题,在他介绍折叠式或大多数Haskell思想之前,这是一个问题。

如果你想“手动”编写求和函数,它将只是第一个元素加上剩余元素的总和:

sum' :: Num a => [a] -> a

-- The sum of an empty list is 0
-- The "base case" of the recursion
sum' [] = 0

-- The sum of a non-empty list is equal to the first element
-- plus the sum of the rest of the list 
sum' (x:xs) = x + (sum' xs)
这很好,但过了一会儿,你就会意识到你将经常使用这种模式:在维护累加器的同时循环列表。在这种情况下,数字的总和就是累加器

这就是
fold
s的用武之地。对折叠工作原理的完整描述是不可能的,但要使用折叠对数字列表求和,您只需写下:

sum' :: Num a => [a] -> a
sum' xs = foldl (+) 0 xs
折叠基本上是在列表中的每个元素之间插入您赋予它的函数

foldl (+) 0 [1, 2, 3, 4, 5]
与基本相同(注意左边的0,这是起始和):


关于折叠的更多信息,我写了一个答案(在许多其他答案中)。值得一看。

如果要“手动”编写求和函数,只需将第一个元素加上其余元素之和即可:

sum' :: Num a => [a] -> a

-- The sum of an empty list is 0
-- The "base case" of the recursion
sum' [] = 0

-- The sum of a non-empty list is equal to the first element
-- plus the sum of the rest of the list 
sum' (x:xs) = x + (sum' xs)
这很好,但过了一会儿,你就会意识到你将经常使用这种模式:在维护累加器的同时循环列表。在这种情况下,数字的和是累加器

这就是
fold
s的用武之地。对折叠工作原理的完整描述是不可能的,但要使用折叠对数字列表求和,您只需写下:

sum' :: Num a => [a] -> a
sum' xs = foldl (+) 0 xs
折叠基本上是在列表中的每个元素之间插入您赋予它的函数

foldl (+) 0 [1, 2, 3, 4, 5]
与基本相同(注意左边的0,这是起始和):


关于折叠的更多信息,我写了一个答案(在许多其他答案中)。值得一看。

如果你了解咖喱,你可以更简单地使用:

sum' = foldl (+) 0

如果你了解咖喱,你可以更简单地说:

sum' = foldl (+) 0

这正是使用折叠的情况。我认为一个折叠是一个“原语”。总结一个列表,它只是<代码> FordD+数字< /代码>。折叠非常简单,只要你用几次就可以了。你是在尝试对一系列数字求和吗?如果这是你的问题,我会写一个答案。现在还不清楚你到底想做什么。你能解释一下你想用
drop(succ(elemIndex x xs))xs
部分实现什么吗?你的问题表明你的函数应该“对列表的内容求和”。然而,它显然是打算做些别的事情。它正在添加列表中的一些元素,但不是全部
drop(succ(elemIndex x xs))xs
甚至不进行打字检查(
elemIndex
产生
可能是Int
)。如果该部分确实起作用,它将删除
xs
的前缀,该前缀位于另一个
x
出现之前(并在
x
不在
xs
中时执行..)。您能否正确描述
sum'
的预期语义?这正是使用折叠的确切情况。我认为一个折叠是一个“原语”。总结一个列表,它只是<代码> FordD+数字< /代码>。折叠非常简单,只要你用几次就可以了。你是在尝试对一系列数字求和吗?如果这是你的问题,我会写一个答案。现在还不清楚你到底想做什么。你能解释一下你想用
drop(succ(elemIndex x xs))xs
部分实现什么吗?你的问题表明你的函数应该“对列表的内容求和”。然而,它显然是打算做些别的事情。它正在添加列表中的一些元素,但不是全部
drop(succ(elemIndex x xs))xs
甚至不进行打字检查(
elemIndex
产生
可能是Int
)。如果该部分确实起作用,它将删除
xs
的前缀,该前缀位于另一个
x
出现之前(并在
x
不在
xs
中时执行..)。您能否正确描述
sum'
的预期语义。你对foldl的解释很好。我不知道它可以写得像你的第一个答案那么简单。3.Haskell社区似乎比许多其他社区更加理解!我原以为会被人遗忘。相反,我得到了一个很好的答案,并学到了一些东西。谢谢。但是我应该注意,您给
foldl
的函数不需要像数学运算符那样简单。折叠+匿名函数=非常简洁的循环。你对foldl的解释很好。我不知道它可以写得像你的第一个答案那么简单。3.Haskell社区似乎比许多其他社区更加理解!我原以为会被人遗忘。相反,我得到了一个很好的答案,并学到了一些东西。谢谢。但是我应该注意,您给
foldl
的函数不需要像数学运算符那样简单。折叠+匿名函数=非常简洁的循环。