问题
While I understand a little about currying in the mathematical sense, partially applying an infix function was a new concept which I discovered after diving into the book Learn You a Haskell for Great Good.
Given this function:
applyTwice :: (a -> a) -> a -> a
applyTwice f x = f (f x)
The author uses it in a interesting way:
ghci> applyTwice (++ [0]) [1]
[1,0,0]
ghci> applyTwice ([0] ++) [1]
[0,0,1]
Here I can see clearly that the resulting function had different parameters passed, which would not happen by normal means considering it is a curried function (would it?). So, is there any special treatment on infix sectioning by Haskell? Is it generic to all infix functions?
As a side note, this is my first week with Haskell and functional programming, and I'm still reading the book.
回答1:
Yes, you can partially apply an infix operator by specifying either its left or right operand, just leaving the other one blank (exactly in the two examples you wrote).
So, ([0] ++)
is the same as (++) [0]
or \x -> [0] ++ x
(remember you can turn an infix operator into a standard function by means of parenthesis), while (++ [0])
equals to \x -> x ++ [0]
.
It is useful to know also the usage of backticks, ( `` ), that enable you to turn any standard function with two arguments in an infix operator:
Prelude> elem 2 [1,2,3]
True
Prelude> 2 `elem` [1,2,3] -- this is the same as before
True
Prelude> let f = (`elem` [1,2,3]) -- partial application, second operand
Prelude> f 1
True
Prelude> f 4
False
Prelude> let g = (1 `elem`) -- partial application, first operand
Prelude> g [1,2]
True
Prelude> g [2,3]
False
回答2:
Yes, this is the section syntax at work.
Sections are written as ( op e )
or ( e op )
, where op is a binary operator and e is an expression. Sections are a convenient syntax for partial application of binary operators.
The following identities hold:
(op e) = \ x -> x op e
(e op) = \ x -> e op x
回答3:
All infix operators can be used in sections in Haskell - except for -
due to strangeness with unary negation. This even includes non-infix functions converted to infix by use of backticks. You can even think of the formulation for making operators into normal functions as a double-sided section:
(x + y)
->(+ y)
->(+)
Sections are (mostly, with some rare corner cases) treated as simple lambdas. (/ 2)
is the same as:
\x -> (x / 2)
and (2 /)
is the same as \x -> (2 / x)
, for an example with a non-commutative operator.
There's nothing deeply interesting theoretically going on here. It's just syntactic sugar for partial application of infix operators. It makes code a little bit prettier, often. (There are counterexamples, of course.)
来源:https://stackoverflow.com/questions/10131300/partial-application-with-infix-functions