12

I'm having trouble with understanding how function application works with currying in haskell. If I have following function:

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

I understand that to partially apply this function I need to provide (a -> b) function ($'s first argument).

Why then is it possible to apply a value first (i.e. reverse arguments)?

($ 0) :: Num a => (a -> b) -> b

What am I missing here?

4

4 回答 4

14

($)是一个运算符。在 Haskell 中,任何运算符都可以写在左侧(如(x $))或右侧(如($ x))中:

(x $) = (\y -> x $ y) = ($) x
($ x) = (\y -> y $ x) = flip ($) x

请注意,此规则的唯一例外是(-),为了方便地写负数:

\x -> (x-) :: Num a => a -> a -> a  -- equivalent to \x -> (-) x
\x -> (-x) :: Num a => a -> a       -- equivalent to \x -> negate x

如果您想简洁地编写(\y -> y - x),可以使用subtract

\x -> subtract x :: Num a => a -> a -> a  -- equivalent to \x -> flip (-) x
于 2013-01-18T21:09:27.373 回答
4

($ 0)(\x -> x $ 0)(\x -> ($) x 0)

如果我们像我们($) :: (a -> b) -> a -> b)一样应用了第二个参数(\x -> ($) x 0):: Num a => (a -> b) -> b

于 2013-01-18T21:08:07.900 回答
2

您将运算符的中缀表示法与函数混淆了。

> :t (($) (+1))
(($) (+1)) :: Num b => b -> b

$为了更好地理解,这里有一些表达形式:

a $ b => ($) ab

($ b) => 翻转 ($) b => (\ba -> ($) ab) b => \a -> ($) ab

(a $) => ($) a => \b -> ($) ab

于 2013-01-18T21:11:49.507 回答
1

另请注意,在 Haskell 语法中,字母数字名称与标点名称不同。

字母数字函数foo1 a b默认为前缀,如果添加反引号,则变为中缀:a `foo` b

标点命名的函数默认为$or<*>中缀,如果添加括号($)or则成为前缀(<*>)。对于熟悉拉丁字母的程序员来说,这只是语法糖;这是字母数字名称和标点名称之间的任意但有用的区别。

这两种函数都只是函数,它们没有我们在 C++ 或 Java 中为“运算符”所拥有的特殊语义规则。只是围绕前缀/中缀和反引号/括号的语法规则在标点符号命名的函数和字母数字命名的函数之间有所不同。

于 2013-12-28T01:09:57.107 回答