点(.)和美元符号($)的区别是什么?
根据我的理解,它们都是不需要使用括号的语法糖。
点(.)和美元符号($)的区别是什么?
根据我的理解,它们都是不需要使用括号的语法糖。
当前回答
还要注意,($)是专门用于函数类型的标识函数。恒等函数是这样的:
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)
其他回答
$操作符用于避免括号。在它之后出现的任何东西都会优先于在它之前出现的任何东西。
例如,假设你有一行是这样写的:
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
它们有不同的类型和不同的定义:
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
换句话说,在$s链中,除了最后一个,其他的都可以被。
关于$最重要的部分是它具有最低的操作符优先级。
如果你输入info,你会看到:
λ> :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
这告诉我们它是一个具有右结合性的中缀运算符,具有最低的可能优先级。普通函数应用程序是左关联的,具有最高优先级(10)。$正好相反。
所以我们在普通函数application或using()不起作用的地方使用它。
例如,这是可行的:
λ> head . sort $ "example"
λ> e
但这不是:
λ> head . sort "example"
因为。(sort "example")的优先级比sort低,类型是[Char]
λ> :type (sort "example")
(sort "example") :: [Char]
但是。需要两个函数,没有一个简单的方法来实现因为排序和操作的顺序。
学习任何东西(任何函数)的一个好方法是记住所有东西都是函数!一般的咒语是有帮助的,但在特定的情况下,比如运算符,它有助于记住这个小技巧:
:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
and
:t ($)
($) :: (a -> b) -> a -> b
只需记住大量使用:t,并将操作符包装在()中!
... 或者你可以避免。和$ structures使用管道:
third xs = xs |> tail |> tail |> head
这是在你添加了helper函数之后:
(|>) x y = y x