我只想知道我们如何知道哪些函数需要括号()而哪些函数不需要?例如
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
工作正常。但
replicate 100 (product (map (*3) (zipWith (max [1,2,3,4,5] [4,5,6,7,8]))))
不起作用。这是因为我为zipWith添加了一组括号。在这个小例子中,zipWith和max没有括号,但是复制,产品和地图都有。一般来说,有一种方法可以知道/确定哪些功能需要括号,哪些功能不需要。
答案 0 :(得分:11)
函数应用程序是左关联的。所以,当你写一个像:
这样的表达式时f g h x
意思是:
((f g) h) x
zipWith
的类型也提供了线索:
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
它说zipWith
有3个参数:一个函数和两个列表。
当你写:
zipWith (max [1,2,3,4,5] [4,5,6,7,8])
口译员会理解
max [1,2,3,4,5] [4,5,6,7,8]
将是zipWith的第一个参数,类型不正确。请注意zipWith
期望两个参数的函数作为其第一个参数,并且正如@Cubic指出的那样,max [1,2,3,4,5] [4,5,6,7,8]
将返回最大值
根据通常的词典顺序(类型为[a]
),这两个列表之间的某些类型a
是Ord
和Num
的实例。说,由于您尝试传递类型
(Num a, Ord a) => [a]
其中值为
(a -> b -> c)
预计。
答案 1 :(得分:4)
这就像学校数学一样:
3 * (4+5)
+
表达式不需要使用括号,而*
表达式通常不需要 。
在Haskell中,你总是可以在没有括号的情况下离开。无论何时需要将表达式括在括号中,另一种方法是引入本地名称并将其绑定到该表达式,然后使用名称而不是表达式。
在你的例子中:
replicate 100 (product (map (*3) (zipWith max [1,2,3,4,5] [4,5,6,7,8])))
let list1 = product list2
list2 = map thrice list3
thrice x = x*3
list3 = zipWith max [1,2,3,4,5] [4,5,6,7,8]
in replicate 100 list1
事实上,我经常自上而下编写函数:
foo x y z = result
where
result = ...
...
然而,正如之前所说的,通过使用(.)
和($)
,通常可以在没有括号的情况下编写包含函数应用程序的表达式,在这种情况下,从上面自上而下的方法可能过于冗长,以下内容会多更清晰(因为新引入的名称没有噪音):
replicate 100
. product
. map (*3)
$ zipWith max [1..5] [4..8]