如果我在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相同,除了它给出了长度不匹配的错误。它处理了我遇到的一些极端情况,并获得了预期的结果。
单独计算参数列表的长度不是一个好主意。我们通常希望消耗尽可能少的输入,而产生尽可能多的输出。这被称为“不要强迫输入太多”,即尽可能懒惰。
在您的情况下,当我们分析两个参数时,如果一个列表为空而另一个列表不是,则将知道长度不匹配:
listAdd :: [Float] -> [Float] -> [Float]
listAdd (x:xs) (y:ys) = (x+y) : listAdd ... ...
listAdd [] [] = []
listAdd _ _ = error "length mismatch"
这样,它甚至适用于无限列表。
与此类似的内置函数是zipWith
,但它忽略列表长度不匹配:
Prelude> zipWith(+) [1,2] [3]
[4]
它等效于上面的定义,最后两行用catch-all子句代替
listAdd _ _ = []
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句