为什么即使在以下示例中,n-reduction也不适用于滤波器?

Nai*_*air 2 haskell

我正在关注'快速而艰难地学习Haskell'并且我能够完成大部分工作,但我对以下代码示例有两个问题.

  1. 在第一个函数中,为什么我不需要,l但在第二个版本中我需要l?
  2. 在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)

bhe*_*ilr 6

您实际上也可以删除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.