Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 在Haskell中查看列表_List_Haskell - Fatal编程技术网

List 在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 (

我是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 (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