【发布时间】:2014-02-15 23:12:42
【问题描述】:
如果我在 Haskell 中有两个大小相同的列表
list1 = [1.0,2.0,3.0]
list2 = [3.0,5.0,7.0]
我将如何执行元素相加来创建第三个相同大小的列表?
[4.0,7.0,10.0]
具体来说,我想做一个这样的函数:
listAdd :: [Float] -> [Float] -> [Float]
listAdd a b
| length a /= length b = error "length mismatch"
otherwise = ????
我不知道用什么来代替“????”。我认为它必须涉及'map'和某些版本的'+',但是部分评估的事情让我感到困惑,并且正确的语法被证明是难以捉摸的。
编辑 1:
我以为我理解了与 cons 运算符的模式匹配,所以我接下来尝试了这个:
listAdd :: [Float] -> [Float] -> [Float]
listadd (x:xs) (y:ys) = (x+y) : listAdd xs ys
listAdd [] [] = []
listAdd _ _ = error "length mismatch"
但是还是有问题,如
listAdd [1.0,2.0] [2.0,3.0]
跳过有用的模式并返回错误。
编辑 2:
消除错别字,
listAdd :: [Float] -> [Float] -> [Float]
listAdd (x:xs) (y:ys) = (x+y) : listAdd xs ys
listAdd [] [] = []
listAdd _ _ = error "length mismatch"
按广告宣传。由于在我研究的早期阶段,管理任意维度张量的类型超出了我的能力范围,因此我决定仅将其扩展到矩阵加法:
mAdd :: [[Float]] -> [[Float]] -> [[Float]]
mAdd (x:xs) (y:ys) = listAdd x y : mAdd xs ys
mAdd [] [] = []
mAdd _ _ = error "length mismatch"
我意识到将功能捆绑在一起可能并不理想,因为它会降低模块化/可移植性,但它可以满足我的需要。
编辑 3:
我希望现在宣布某种程度的学习已经发生还为时过早。我现在有这个:
listCombine :: (Float -> Float -> Float) -> [Float] -> [Float] -> [Float]
listCombine f (x:xs) (y:ys) = (f x y) : listCombine f xs ys
listCombine f [] [] = []
listCombine _ _ _ = error "length mismatch"
这可能与 zipWith 相同,只是它会因长度不匹配而出错。它处理了我扔给它的极端案例并取得了预期的结果。
【问题讨论】:
-
虽然您可以像以前一样使用显式递归,但在列表长度相等的情况下,更惯用的 Haskell 版本只是
zipWith (+)。 -
在这种情况下,我想长期坚持下去。我希望在让它与列表一起工作之后,我将看到如何扩展它以按元素添加任意大小的张量。知道为什么我的功能不起作用吗?
-
@user2790167 你有一个错字:
listadd (x:xs) (y:ys) =应该是listAdd (x:xs) (y:ys) =。我猜你没有复制粘贴我发布的代码,而是重新输入了它。 -
我不敢相信我打错了。感谢您指出这一点。
-
好的,我想我明白了。您使用
listCombine f (x:xs) (y:ys) = (f x y) : listCombine f xs ys对未指定的函数 f 进行模式匹配。