我正在用 Haskell 做 Project Euler,并在完成第一个问题时找到了要学习的东西。这是我的代码:
isValid x = (mod x 3 == 0) || (mod x 5 == 0)
listValid :: Integer -> [Integer]
listValid n = [x | x <- [1..n-1], isValid x]
该函数listValid
将得到所有小于n
可以被 3 或 5 整除的正整数。很简单。
*Main> listValid 10
[3,5,6,9]
现在我需要总结它们。我认为 sum 函数是正确的方法。我不明白的是为什么前两个版本有效,然后第三个版本无效。
*Main> sum (listValid 10)
23
*Main> sum $ listValid 10
23
*Main> sum listValid 10
<interactive>:4:5:
Couldn't match type ‘[Integer]’ with ‘a0 -> t’
Expected type: Integer -> a0 -> t
Actual type: Integer -> [Integer]
Relevant bindings include it :: t (bound at <interactive>:4:1)
In the first argument of ‘sum’, namely ‘listValid’
In the expression: sum listValid 10
这是一个操作顺序问题,我需要用括号括起来以断言应该首先应用哪个函数?如果是$
这样,第二个版本在做什么?
这是关于关联性的。函数应用程序是左关联的,所以sum listValid 10
等价于(sum listValid) 10
,而不是sum (listValid 10)
。如果你考虑一下,它必须是这样的:如果你定义了add x y = x+y
,你不会想要add 1 2
等同于add (1 2)
。
所以这里的问题是,在 中sum listValid 10
,它不认为listValid 10
是sum
; 它认为listValid
是 的参数sum
,然后10
是 的参数sum listValid
。
$
解决了这个问题,因为它是一个中缀运算符,并且非常清楚sum
它的左操作数listValid 10
是它的右操作数(请记住,函数应用程序的优先级高于任何中缀运算符,因此它不能被视为(sum $ listValid) 10
)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句