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

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


当前回答

它们有不同的类型和不同的定义:

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链中,除了最后一个,其他的都可以被。

其他回答

学习任何东西(任何函数)的一个好方法是记住所有东西都是函数!一般的咒语是有帮助的,但在特定的情况下,比如运算符,它有助于记住这个小技巧:

:t (.)
(.) :: (b -> c) -> (a -> b) -> a -> c

and

:t ($)
($) :: (a -> b) -> a -> b

只需记住大量使用:t,并将操作符包装在()中!

关于$最重要的部分是它具有最低的操作符优先级。

如果你输入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]

但是。需要两个函数,没有一个简单的方法来实现因为排序和操作的顺序。

它们有不同的类型和不同的定义:

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链中,除了最后一个,其他的都可以被。

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

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

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

(|>) x y = y x

($)允许函数链接在一起,而不需要添加括号来控制求值顺序:

Prelude> head (tail "asdf")
's'

Prelude> head $ tail "asdf"
's'

复合操作符(.)创建一个新函数,但不指定参数:

Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'

Prelude> let second = head . tail
Prelude> second "asdf"
's'

上面的例子可以说是说明性的,但并没有真正显示使用组合的便利性。这里还有一个类比:

Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"

如果我们只使用一次third,我们可以通过使用lambda来避免命名:

Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"

最后,复合让我们避免lambda:

Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"