$
运算符用于避免括号。之后出现的所有内容将优先于之前出现的所有内容。
例如,假设您的一行显示为:
putStrLn (show (1 + 1))
如果要删除这些括号,则以下任何一行都将执行相同的操作:
putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1
的主要目的.
运算符不是要避免括号,而是要链接函数。它使您可以将右侧显示的输出与左侧显示的输入绑定在一起。通常,这也会导致较少的括号,但工作方式有所不同。
回到同一个例子:
putStrLn (show (1 + 1))
(1 + 1)
没有输入,因此不能与一起使用.
操作员。show
可以接受一个Int
并返回一个String
。putStrLn
可以使用String
并返回IO ()
。您可以像这样将show
到putStrLn
(putStrLn . show) (1 + 1)
如果您喜欢的括号太多,请使用$
运算符将其删除:
putStrLn . show $ 1 + 1
它们具有不同的类型和不同的定义:
infixr 9 .
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(f . g) x = f (g x)
infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x
($)
旨在替换常规函数应用程序,但具有不同的优先级以帮助避免括号。 (.)
用于将两个函数组成一个新函数。
在某些情况下,它们是可互换的,但这通常是不正确的。它们所在的典型示例是:
f $ g $ h $ x
==>
f . g . h $ x
换句话说,在$
的链中,除最后一个以外的所有.
另请注意, ($)
是专用于函数类型的标识函数。身份函数如下所示:
id :: a -> a
id x = x
虽然($)
看起来像这样:
($) :: (a -> b) -> (a -> b)
($) = id
请注意,我有意在类型签名中添加了额外的括号。
通常可以通过添加括号来消除对($)
使用(除非在节中使用了运算符)。例如: f $ gx
变为f (gx)
。
(.)
用法通常较难替换;他们通常需要 lambda 或引入显式函数参数。例如:
f = g . h
变成
f x = (g . h) x
变成
f x = g (h x)
希望这可以帮助!