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

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


当前回答

一个很有用的应用程序,我花了一些时间从Learn You a Haskell非常简短的描述中弄清楚:Since

f $ x = f x

在包含中缀运算符的表达式的右边加圆括号将其转换为前缀函数,可以将($ 3)(4 +)写成类似于(++ ",world")“你好”。

为什么会有人这么做?例如,对于函数列表。两个:

map (++ ", world") ["hello", "goodbye"]
map ($ 3) [(4 +), (3 *)]

map (\x -> x ++ ", world") ["hello", "goodbye"]
map (\f -> f 3) [(4 +), (3 *)]

显然,后一种变体对大多数人来说更具可读性。

其他回答

简短而甜蜜的版本:

($)调用作为其左实参的函数对作为其右实参的值进行调用。 (.)将作为其左参数的函数组合到作为其右参数的函数上。

... 或者你可以避免。和$ structures使用管道:

third xs = xs |> tail |> tail |> head

这是在你添加了helper函数之后:

(|>) x y = y x

还要注意,($)是专门用于函数类型的标识函数。恒等函数是这样的:

id :: a -> a
id x = x

While($)是这样的:

($) :: (a -> b) -> (a -> b)
($) = id

注意,我有意在类型签名中添加了额外的括号。

($)的使用通常可以通过添加圆括号来消除(除非在节中使用运算符)。例如:f $ g x变成f (g x)。

(.)的使用通常稍难替换;它们通常需要一个lambda或显式函数形参的引入。例如:

f = g . h

就变成了

f x = (g . h) x

就变成了

f x = g (h x)

我的规则很简单(我也是初学者):

不要使用。如果要传递参数(调用函数),和 如果没有参数,不要使用$(合成一个函数)

这是

show $ head [1, 2]

但从来没有:

show . head [1, 2]

$操作符用于避免括号。在它之后出现的任何东西都会优先于在它之前出现的任何东西。

例如,假设你有一行是这样写的:

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

你可以这样链式显示strln:

(putStrLn . show) (1 + 1)

如果括号太多,可以用$操作符去掉:

putStrLn . show $ 1 + 1