Partial Application with Infix Functions

2.8k views Asked by At

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.

3

There are 3 answers

2
Riccardo T. On BEST ANSWER

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
3
Carl On

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.)

0
Don Stewart On

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