我是Haskell的初学者,所以我在使用严格类型的东西时会苦苦挣扎,只是想知道是否有人可以帮助我使用我正在尝试构建的函数。基本上,它需要一个列表列表,例如:
[[1,2,3], [7,6,8], [0,3,4]]
并将它们一起添加到一个列表中,通过沿着它的位置数来翻译后面的列表。因此,在示例列表上工作实际上会执行以下操作:
foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]
这是我当前的函数(获取类型错误):
addLists :: [[Integer]] -> [Integer]
addLists [[]] = []
addLists [[x]] = [x]
addLists [x:xs] = zipWith (+) [x] ([0]++ (addLists xs))
答案 0 :(得分:6)
请注意,([0]++)
与(0:)
相同,这会使它看起来更整洁并为我们节省一两纳秒。
(我正在用纳秒级的东西开玩笑 - 没有人能分辨出什么东西的速度快一纳秒,但无论如何它都更好。)
让我们首先考虑制作您需要的列表。我们想要
postponeLists [[1,2,3], [7,6,8], [10,20,30,40]]
= [[1,2,3], [0,7,6,8], [0,0,10,20,30,40]]
= [1,2,3] : ones that should have zero in front of them
这是定义的足够信息:
postponeLists [] = []
postponeLists (l:ls) = l : map (0:) (postponeLists ls)
现在你说
foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]
但你的意思是
foldl (zipWith (+)) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]
但不幸的是,这会给你[]
因为zipWith
会在任何列表用完元素后立即停止。
我们需要某种方式来压缩它们并不会停止。
解决方案1:找到最长的一个,使用maxlength
生成take maxlength.(++ repeat 0)
的所有内容
解决方案2:编写另一个不会停止的zipWith函数。
我更喜欢解决方案2.让我们看一下definition of zipWith
zipWith :: (a->b->c) -> [a]->[b]->[c]
zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
zipWith _ _ _ = [] -- here's the problem - it stops as soon as any list is empty
好的,我们不要停下来:
zipWithMore :: (a -> a -> a) -> [a] -> [a] -> [a]
zipWithMore f (a:as) (b:bs) = f a b : zipWithMore f as bs
zipWithMore f [] bs = bs -- if there's more in bs, use that
zipWithMore f as [] = as -- if there's more in as, use that
现在,您可以将zipWith (+)
替换为zipWithMore (+)
。我会给你留下妙语。
答案 1 :(得分:3)
我认为这可以做你想要的事情
import Data.List (transpose)
addLists :: Num a => [[a]] -> [a]
addLists xs = map sum . transpose $ zipWith (\n x -> replicate n 0 ++ x) [0..] xs