理解这一点的诀窍在于,所有的 Haskell 函数最多只接受一个参数,只是类型签名和语法糖中的隐式括号使其看起来像有更多的参数。以
++
为例,以下转换都是等价的。
xs ++ ys = ...
(++) xs ys = ...
(++) xs = \ys -> ...
(++) = \xs -> (\ys -> ...)
(++) = \xs ys -> ...
另一个快速的例子:
doubleList :: [Int] -> [Int]
doubleList = map (*2)
这里我们有一个带有一个参数doubleList
的函数,没有任何显式参数。与其等效的写法是:
doubleList x = map (*2) x
或者以下任何一个。
doubleList = \x -> map (*2) x
doubleList = \x -> map (\y -> y * 2) x
doubleList x = map (\y -> y * 2) x
doubleList = map (\y -> y * 2)
“doubleList” 的第一个定义采用通常所称的无点符号表示法进行编写,它被这样称呼是因为在支持它的数学理论中,参数被称为“点”,因此无点符号即为“没有参数”的意思。
以下是一个更复杂的例子:
func = \x y z -> x * y + z
func = \x -> \y z -> x * y + z
func x = \y z -> x * y + z
func x = \y -> \z -> x * y + z
func x y = \z -> x * y + z
func x y z = x * y + z
现在如果我们想要完全删除对参数的所有引用,我们可以利用点(
. )运算符执行函数组合:
func x y z = (+) (x * y) z
func x y = (+) (x * y)
func x y = (+) ((*) x y)
func x y = ((+) . ((*) x)) y
func x = (+) . ((*) x)
func x = (.) (+) ((*) x)
func x = ((.) (+)) ((*) x)
func x = (((.) (+)) . (*)) x
func = ((.) (+)) . (*)
func = (.) ((.) (+)) (*)
如您所见,有很多不同的方法来编写某个函数,有些具有显式“参数”,非常易读(例如func x y z = x * y + z
),而有些则只是一堆符号的混乱表示,没有什么意义(例如func = (.) ((.) (+)) (*)
)。
(++) [1,2]
是一个可以应用于[4,5]
以生成[1,2,4,5]
的函数。 - chi