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
Haskell中的乘法列表_Haskell - Fatal编程技术网

Haskell中的乘法列表

Haskell中的乘法列表,haskell,Haskell,如何实现将列表中的每个元素乘以另一个列表中相应元素的函数?例如,给定列表[1,2,3]和[4,5,6]返回[4,10,18]?我的代码如下: calcArea :: [Int] -> [Int] -> [Int] calcArea length width = length * width 这是一个典型的用例: 或者,可能更容易理解,但相当于: calcArea length width = zipWith (*) length width @ForceBru已经写了一个非常好的

如何实现将列表中的每个元素乘以另一个列表中相应元素的函数?例如,给定列表
[1,2,3]
[4,5,6]
返回
[4,10,18]
?我的代码如下:

calcArea :: [Int] -> [Int] -> [Int]
calcArea length width = length * width

这是一个典型的用例:

或者,可能更容易理解,但相当于:

calcArea length width = zipWith (*) length width

@ForceBru已经写了一个非常好的答案,但我想探索如何自己编写这种函数

首先,我们可以编写类型签名。你已经有了:

calcArea :: [Int] -> [Int] -> [Int]
现在我们可以写出这两个论点可以采用的四种不同情况:

calcArea []     []     = -- TODO: case 1
calcArea (a:as) []     = -- TODO: case 2
calcArea []     (b:bs) = -- TODO: case 3
calcArea (a:as) (b:bs) = -- TODO: case 4
第一种情况很简单:

calcArea [] [] = []
但第二个和第三个更难。在这里,我将决定“截断”列表,以便
calcArea[1,2,3][]=[]
。此外,这意味着要与相同大小的列表一起使用。如果函数的行为不符合此要求,则可能需要对此进行更改。(请注意,这就是
zipWith
的行为。)此外,由于我们没有引用列表中的元素,因此可以编写
\u
,而不是像前面那样编写
(a:as)
(b:bs)

calcArea _ [] = []
calcArea [] _ = []
(还要注意,这些案例与第一个案例重叠,因此我们可以完全删除第一个案例)

最后,我们有案例4。显然,我们希望在某个列表中包含
a*b
,因此让我们从以下内容开始:

calcArea (a:as) (b:bs) = (a * b) : --???
此时,我们意识到,
calcArea as bs
as
bs
的前两个元素的产物,然后是列表其余部分的
calcArea
!也就是说,
calcrea[1,2,3][4,5,6]=(1*4):calcrea[2,3][5,6]
。因此,我们可以重复:

calcArea (a:as) (b:bs) = (a * b) : calcArea as bs
因此,完整的功能是:

calcArea :: [Int] -> [Int] -> [Int]
calcArea [] _ = []
calcArea _ [] = []
calcArea (a:as) (b:bs) = (a * b) : calcArea as bs
请注意,这相当于
calcArea=zipWith(*)


我希望这能帮助您将来在Haskell中编写更复杂的函数。

@ForceBru的答案是完成这项工作的最简单方法。然而,当您需要“一对一”操作而不是组合操作时,可能会有一些更复杂的作业需要对列表执行函子和应用程序操作。因此,有一种
Control.Applicative.ZipList
类型专门用于此工作,它可能很方便

import Control.Applicative

mult121 :: Num a => [a] -> [a] -> [a]
mult121 xs ys = getZipList $ (*) <$> ZipList xs <*> ZipList ys

*Main> mult121 [1,2,3] [4,5,6]
[4,10,18]
导入控件。应用程序
mult121::Num a=>[a]->[a]->[a]
mult121 xs ys=getZipList$(*)ZipList xs ZipList ys
*Main>mult121[1,2,3][4,5,6]
[4,10,18]

您的意思是“产品”,而不是“总和”。--顺便说一句,我有时喜欢这种解释性(归纳?)编程,当我们从
calcArea[1,2,3][4,5,6]=(1*4):calcArea[2,3][5,6]
calcArea(1:2\u-3)(4:5\u-6)=(1*4):calcArea 2\u-3-5\u-6
时,它也可以作为
fmap-getZipList点写。liftA2(*)`on`ZipList
。虽然我认为在这种情况下这有点不太清楚,但经常值得检查一下无点解决方案是否更好,就像使用
calcrea=zipWith(*)一样。
import Control.Applicative

mult121 :: Num a => [a] -> [a] -> [a]
mult121 xs ys = getZipList $ (*) <$> ZipList xs <*> ZipList ys

*Main> mult121 [1,2,3] [4,5,6]
[4,10,18]