我想总结一个压缩列表。
averageGrade :: [Float] -> [Int] -> Float
averageGrade [0.75 , 0.25] [6, 4] , result: 0,75*6 + 0.25*4 = 5.5
Run Code Online (Sandbox Code Playgroud)
当我去ghci并执行以下操作时:
sum(zipWith (*) [0.75, 0.25] [6, 4])
Run Code Online (Sandbox Code Playgroud)
我确切地得到了我想要的。
但是在代码中我遇到了一个错误,我也不知道为什么。
averageGrade :: [Float] -> [Int] -> Float
averageGrade a b
| a == [] = 0
| b == [] = 0
| otherwise = (sum(zipWith (*) a b))
Run Code Online (Sandbox Code Playgroud)
如果要编译此文件,则会出现以下错误:
Couldn't match type ‘Int’ with ‘Float’
Expected type: [Float]
Actual type: [Int]
In the third argument of ‘zipWith’, namely ‘b’ …
Run Code Online (Sandbox Code Playgroud) 我正在玩一下zipWith
并遇到以下情况:
Prelude Control.Applicative> :t zipWith id
zipWith id :: [b -> c] -> [b] -> [c]
Run Code Online (Sandbox Code Playgroud)
为什么编译器期望下一个参数是一个函数列表?
我试图分析,但无法断定,为什么下一个参数必须是函数列表.
当我id
转到时,签名是如何申请的zipWith
?
我是Haskell的新手,并且遇到了以下使我感到困惑的代码:
foldr (zipWith (:)) (repeat []) [[1,2,3],[4,5,6],[7,8,9,10]]
Run Code Online (Sandbox Code Playgroud)
它产生以下结果,在反复试验之后,我不完全确定为什么:
[[1,4,7],[2,5,8],[3,6,9]]
Run Code Online (Sandbox Code Playgroud)
我的印象是,(:)
将项目添加到列表中,并(repeat [])
产生无数的空列表[]
,并foldr
接受一个函数,一个项目和一个列表,并通过将函数连续应用于列表中的每个项目来压缩列表。列出结果。
也就是说,我直观地理解以下代码如何产生结果10:
foldr (+) 1 [2,3,4]
Run Code Online (Sandbox Code Playgroud)
但是,我完全不确定为什么要使用foldr (zipWith (:)) (repeat [])
一个列表列表并生成另一个列表列表,这些列表中的项按其原始内部索引分组。
任何解释都是有启发性的。
我正在实现一个combine :: [[a]] -> [[b]] -> (a -> b -> c) -> [[c]]
给出两个2D列表的函数,将给定的函数应用于2D列表f :: a -> b -> c
的条目.换一种说法:
[[a, b, c], [[r, s, t], [[f a r, f b s, f c t],
combine [d, e, g], [u, v, w], f = [f d u, f e v, f g w],
[h, i, j]] [x, y, z]] [f h x, f i y, f j z]]
Run Code Online (Sandbox Code Playgroud)
现在我怀疑combine = zipWith . zipWith
,因为我已经尝试过,它给了我预期的结果,例如
(zipWith . …
Run Code Online (Sandbox Code Playgroud) 我在Haskell中看到了斐波那契数的这种实现方式,但我仍在试图弄清楚为什么它可以正常工作。因此,很显然,可以使用zipWith函数以非常紧凑的方式编写斐波那契数。该实现如下所示
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)
为了更好地了解此处发生的情况,我查看了zipWith函数的文档。此函数使用给定的函数(a-> b-> c)将两个列表[a],[b]一起添加。在我们的例子中,该功能是一个简单的添加。如果两个列表[a]和[b]的长度不同(在我们的例子中,列表[b]总是比列表[a]短一个元素),则zipWith只是从两个列表的开头开始并将它们相加。如果到达一个列表的末尾,则无论已到达另一个列表的末尾,它都会停止。
在递归的第一步中,使用[0,1]和tail [0,1] = [1]调用zipWith。这导致另一个1 => [0,1,1]。在递归的第二步中,使用[0,1,1]和[1,1]调用zipWith,导致[0 + 1,1 + 1] = [1,2]。因此,对我来说,很明显,递归创建了正确的斐波那契数字,但是我不完全理解为什么仅将zipWith步骤之后的最后一个数字添加到结果中,而不是整个列表中。也许有人可以向我解释。那会很有帮助。非常感谢你。
lstsAdder :: [[Integer]] -> [Integer]
lstsAdder [] = []
lstsAdder (x:xs) = zipWith (+) x (lstsAdder xs)
Run Code Online (Sandbox Code Playgroud)
正如标题所说,我希望它以递归方式添加:[[a,b,c],[d,e,f]]
就像这样:[a+d,b+e,c+f]
,以及任何有限长度的列表列表.但我所有的实现回报都是[]
.为什么会这样,我该如何解决?