← back

Haskell: Eta reduction and sections

1 February 2017

QUESTION:

Somehow the function to check if a value is less than 0 went from

isLT0 x = x <= 0

to

isLT0 = (<=0)

I don't understand why this is possible.


ANSWER:

In Haskell, we have something called operator sections which is essentially eta reduction on steroids

Consider partial application:

map takes a function a list, returning a list

map :: (a->b) -> [a] -> [b]

I can partially apply map to get a function from list to list

addTwos :: [Int] -> [Int]
addTwos = map (\n -> n+2)

Partial application is a case of eta reduction, I could have written the above as

addTwos ns = map (\n -> n+2) ns

Sections: It is the same for infix operators.

If I define a symbol-looking thing with parens, it becomes an infix operator:

(==) :: Bool -> Bool -> Bool
(==) True True = True
(==) False False = True
(==) _ _  = False

I can call this function like so:

tf1 = (==) True False   -- False

I can also partially apply it:

isTrue = (==) True

But, partial application fills in the parameters from the left. Infix operators are more flexible, I can write the previous as

tf2 = True == False    -- False

Now, I can partially apply on the left or right!

isTrue = (True ==)

isFalse = (== False)

This really passes the parameter at the correct position, to check we can examine the cons operator

(:) :: a -> [a] -> [a]

prependElt :: a -> ([a] -> [a])
prependElt x = (x :)

extendList :: [a] -> (a -> [a])
extendList xs = (: xs)

Try them out in GHCi!

Exercises

  1. show that prependElt is the same as (:)

  2. why can't we eta reduce extendList? can you find a function in the standard library that would allow you to get rid of the explicit xs parameter?

  3. write addTwos with a section