我正在关注'快速而艰难地学习Haskell'并且我能够完成大部分工作,但我对以下代码示例有两个问题.
l但在第二个版本中我需要l?evenSum1,当递归调用函数时,将filter一次又一次地在列表上调用,或者filter在第一次调用时只调用一次?.
evenSum = accumSum 0
where
accumSum n [] = n
accumSum n (x:xs) =
if even x
then accumSum (n+x) xs
else accumSum n xs
evenSum1 l = mysum 0 (filter even l)
where
mysum n [] = n
mysum n (x:xs) = mysum (n+x) xs
Run Code Online (Sandbox Code Playgroud)
您实际上也可以删除l第二个示例,但是您需要切换到所谓的无点表示法并使用函数组合运算符(.):
evenSum1 = mysum 0 . filter even
where
mysum n [] = n
mysum n (x:xs) = mysum (n + x) xs
Run Code Online (Sandbox Code Playgroud)
而且evenSum1,该filter even函数只会被调用一次.会发生什么是filter even用完了传入的列表,然后传递给它的输出mysum 0.
假设你有一个功能add:
add :: Int -> Int -> Int
add x y = x + y
Run Code Online (Sandbox Code Playgroud)
然后你想要一个add5总是加5 的函数Int.你可以这样做
add5 :: Int -> Int
add5 y = add 5 y
Run Code Online (Sandbox Code Playgroud)
但由于函数是Haskell中的第一类对象,我们可以部分应用函数,这相当于说
add5 :: Int -> Int
add5 = add 5
Run Code Online (Sandbox Code Playgroud)
查看它的另一种方法是在类型签名中添加一些可选括号add:
add :: Int -> (Int -> Int)
add x y = x + y
Run Code Online (Sandbox Code Playgroud)
写得像这样,我们可以说这add是一个接受单个Int参数并返回一个新函数的函数Int -> Int.因此,如果我们给出add一个单一的Int,我们就会得到一个新函数.这也是让我们编写表达式的原因
filter even list
Run Code Online (Sandbox Code Playgroud)
代替
filter (\x -> even x) list
Run Code Online (Sandbox Code Playgroud)
对于无点符号,一个好的经验法则是变量可以从最后$变为最后变为.:
f x y = h x $ g y
f x = h x . g
f x y z = h x $ g y $ j z
f x y = h x $ g y . j
Run Code Online (Sandbox Code Playgroud)
这并不总是适用于多参数函数:
f x y = h $ g x y
Run Code Online (Sandbox Code Playgroud)
是不一样的
f = h . g
Run Code Online (Sandbox Code Playgroud)
因为h . g不会打字检查.这是因为隐含的括号:
f x y = h $ (g x) y
f x = h . (g x)
Run Code Online (Sandbox Code Playgroud)
而现在有一些括号可以放弃这个x论点.
另外,请记住这f x y = h (g x y)相当于f x y = h $ g x y,所以你通常可以将最外面的括号变成一个$,可能让你eta-reduce并$改为a ..如果所有这些看起来都令人困惑,你也可以从hackage中获取无点包,其中包含一个命令行工具,可以自动为你执行eta-reduction.
| 归档时间: |
|
| 查看次数: |
111 次 |
| 最近记录: |