从这个周末开始,我正在学习一些Haskell,我发现这门语言很有趣,但也有一些语法让我感到困惑。
例如,zip
是一个函数,它将 2 个列表作为参数,然后返回一个对列表。如果我在ghci
中调用zip [1,2,3] [3,2,1]
,我会得到[(1,3),(2,2),(3,1)]
.但是如果我说(zip [1,2,3]) [3,2,1]
它会返回相同的结果。
当我使用 :i zip
查看 zip 函数的定义时,我得到了zip :: [a] -> [b] -> [(a, b)] -- Defined in ‘GHC.List’
,由此看来zip
是一个函数应用第一个参数,返回一个函数,然后应用于第二个参数。
另一个例子是elem
、elem 1 [1,2,3]
、(elem 1) [1,2,3]
和(1 `elem`) [1,2,3]
返回相同的结果。
所以我的问题是,如果一个函数接收多个参数,这个函数如何计算、按顺序处理每个参数,或者只是一次处理所有参数。
(->)
是正确的关联¹,这意味着像这样:
zip :: [a] -> [b] -> [(a, b)]
被全康理解为:
zip :: [a] -> ([b] -> [(a, b)])
后者可以帮助您看到,当您使用一个参数调用zip
时,您会返回一个函数:
λ> :t zip [1, 2, 3]
zip [1, 2, 3] :: Num a => [b] -> [(a, b)]
这称为currying
或部分应用程序。
笔记
- 右
关联意味着运算符向右分组。一个常见的例子是幂运算符
^
。在电力塔中,这一点很明显:λ> 2^2^2^2 65536 λ> 2^(2^(2^2)) 65536
如果幂运算符是左关联运算符,我们将有:
λ> ((2^2)^2)^2 256