协慌网

登录 贡献 社区

之间有什么区别。 (点)和 $(美元符号)?

(.)和美元符号($)什么区别?

据我了解,它们都是不需要使用括号的语法糖。

答案

$运算符用于避免括号。之后出现的所有内容将优先于之前出现的所有内容。

例如,假设您的一行显示为:

putStrLn (show (1 + 1))

如果要删除这些括号,则以下任何一行都将执行相同的操作:

putStrLn (show $ 1 + 1)
putStrLn $ show (1 + 1)
putStrLn $ show $ 1 + 1

的主要目的.运算符不是要避免括号,而是要链接函数。它使您可以将右侧显示的输出与左侧显示的输入绑定在一起。通常,这也会导致较少的括号,但工作方式有所不同。

回到同一个例子:

putStrLn (show (1 + 1))
  1. (1 + 1)没有输入,因此不能与一起使用.操作员。
  2. show可以接受一个Int并返回一个String
  3. putStrLn可以使用String并返回IO ()

您可以像这样将showputStrLn

(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)

希望这可以帮助!