List 在Haskell中查看列表
我是Haskell的初学者,所以我对严格类型的东西有些费劲,只是想知道是否有人能帮我构建一个函数。基本上,它需要一个列表列表,例如:List 在Haskell中查看列表,list,haskell,List,Haskell,我是Haskell的初学者,所以我对严格类型的东西有些费劲,只是想知道是否有人能帮我构建一个函数。基本上,它需要一个列表列表,例如: [[1,2,3], [7,6,8], [0,3,4]] 并将它们添加到一个列表中,根据其上的位置数转换后面的列表。因此,在示例列表中,它实际上会执行以下操作: foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]] 下面是我当前的函数(它获取类型错误): 我想这正是你想要的 import Data.List (
[[1,2,3], [7,6,8], [0,3,4]]
并将它们添加到一个列表中,根据其上的位置数转换后面的列表。因此,在示例列表中,它实际上会执行以下操作:
foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]]
下面是我当前的函数(它获取类型错误):
我想这正是你想要的
import Data.List (transpose)
addLists :: Num a => [[a]] -> [a]
addLists xs = map sum . transpose $ zipWith (\n x -> replicate n 0 ++ x) [0..] xs
请注意,([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:找到最长的一个,使用take maxlength.(++重复0)
解决方案2:编写另一个zipWith函数,该函数不会停止 我更喜欢解决方案2。让我们看一下 好吧,那我们就不停了:
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(+)
替换为zipWith(+)
。我将把笑话留给您。请明确说明您希望添加列表[[1,2,3],[7,6,8],[0,3,4]的结果是什么。从你的问题上看,这并不明显。看来你已经编辑了你的问题来澄清它,但我恐怕还是不明白。addlist[[1,2,3]、[7,6,8]、[0,3,4]]
的结果应该是什么样的?您给出的示例,foldl(zipWith+[[1,2,3],[0,7,6,8],[0,0,0,3,4]
没有进行类型检查,我无法理解您想要它做什么。是否希望结果是[1,2+7,3+6+0,8+4,4]
=[1,9,9,12,4]
?对不起,输出应该是[1,2+7,3+6+0,8+3],谢谢,你能确切地解释一下它是如何工作的吗?我几乎可以理解,但不完全理解@抱歉,我本想回来扩展这个答案,但出现了其他问题。我希望你很快就会明白的!更好一点:addLists=map sum。转置zipWith(++)(初始化(重复0))
。有趣的部分是转置
,这是一个值得熟悉的数据列表
函数。由于这是一个组合,您可以单独使用每个部分来了解它的工作原理。(0:)
不会在([0]+)
上为您节省任何纳秒,至少在ghc-O2
上不会<代码>(:)
有时比(++)
更好,两者都适用,但你不应该让这种毫微秒的猜测影响你的代码。@shachaf当然不是!我开玩笑地说“节省一到两纳秒”这是不必要的<代码>(0:)更好,我想介绍一下这个习惯。谁会在乎这样的问题会持续几纳秒?我已经说得更清楚了,这不是认真的。
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