问题描述
我正在尝试创建列表的总和,但仅创建大于8的数字。
sum :: [Int] -> Int
sum[] = 0
sum (x:xs) | x > 8 = x
| x < 8 = 0
sum (x:xs) = sum xs + x
main :: IO ()
main = do
print(sum [1,2,3,4,5,6,7,8,9,10,11,12])
所以我希望它加起来9-12并给出42的输出,但是相反它只给出0。 如果我删除了先决条件,则它会正常工作,并对整个列表求和,得出78。 我已经尝试了好几个小时,但仍然无法获得更多的建议,我们将不胜感激。谢谢。
解决方法
您的第二个子句不会递归。因此,这意味着如果x > 8
,它将返回x
,如果x < 8
,它将返回0
。仅在x
恰好为8
的情况下,才会将x
加到其余元素的总和上,但是如果第二个元素不是{{1} }。
因此,您需要在8
或x > 8
的两种情况下都要递归:
x <= 8
但是,您不需要为此进行显式递归。您可以使用内置的sum :: (Foldable f,Num a) => f a -> a
函数对元素求和,并使用filter :: (a -> Bool) -> [a] -> [a]
来过滤元素列表:
sum8 :: [Int] -> Int
sum8 [] = 0
sum8 (x:xs) | x > 8 = x + sum xs
| otherwise = sum xs
或者我们甚至可以通过以下方式推广该函数以与所有sum8 :: (Num a,Ord a) => [a] -> a
sum8 = sum . filter (8 <)
类型一起使用:
Foldable
这将因此适用于各种sum8 :: (Foldable f,Num a,Ord a) => f a -> a
sum8 = foldr f 0
where f x | x > 8 = (x +)
| otherwise = id
,例如列表(Foldable
),Tree
s,Maybe
s等。