CSE 230: Winter 2013

Higher Order Functions

Ranjit Jhala, UC San Diego

module HigherOrder where
import Prelude hiding ((++))

Plan

Functions Are Data

Functions Are Data

Lets define two functions ...

plus1 :: Int -> Int
plus1 x = x + 1

minus1 :: Int -> Int
minus1 x = x - 1

... we can manipulate functions like ordinary data

aPairOfFuns   = (plus1, minus1)
aListOfFuns   = [plus1, minus1, plus1, minus1]
aBigListoFuns = replicate 10 plus1 ++ replicate 5 minus1

The Type is Very Descriptive

ghci> :type aBigListoFuns
aBigListoFuns :: [Int -> Int]

A Big Deal: Can Pass Functions Around

Taking Functions as Input

doTwice f x = f (f x)

Takes as input

and returns as output

Taking Functions as Input

doTwice f x = f (f x)

Lets run it,

ghc> doTwice plus1 10
12
ghc> doTwice minus1 100
98

Taking Functions as Input

doTwice f x = f (f x)

Execution = Substitute Equals for Equals

doTwice plus1 10 
  == {- unfold doTwice -} 
     plus1 (plus1 10)   
  == {- unfold plus1 -}
     plus1 (10 + 1)
  == {- unfold plus1 -}
     (10 + 1) + 1
  == {- old-school arithmetic -}
     12

Returning Functions as Output

Instead of writing plus1, plus2, plus3 ...

plusn :: Int -> (Int -> Int)
plusn n = f
          where f x = x + n

We can now use the above to write

plus2   = plusn 2
plus10  = plusn 10
minus20 = plusn (-20)       -- why the parens?

which can be used ...

ghc> plus10 100
110

ghc> minus20 1000
980 

Returning Functions as Output

You can derive the result by substitutions...

plus10 100

  == {- unfold plus10 -}
     (plusn 10) 100 

  == {- unfold plusn  -}
     f 100
     where f x = x + 10 

  == {- unfold f -}
     100 + 10 

  == {- arithmetic -}
     110

Partial Application

Partial Application

- and -> are operators

- is an operator on integers

-> is an operator on types

Partial Application

- and -> are operators

- is Left-Associative

2 - 1 - 1 == (2 - 1) - 1 == 0


-> is Right-Associative

Int -> Int -> Int == Int -> (Int -> Int)

Partial Application

plus :: Int -> Int -> Int
plus n x = n + x

Here, plus actually has type (Haskell hides ugly parens)

plus :: Int -> (Int -> Int)

So plus

Partial Application

plus :: Int -> Int -> Int
plus n x = n + x

Needn't pass all arguments to plus

A Partially Applied plus

plus100 = plus 100
ghci> plus100 566 
666

Quiz: Have you been following so far?

ex1 = doTwice (plus 99)
  1. What is the type of ex1 ?

  2. What is the value of ex1 100 ?

Anonymous Functions

Functions With No Name

Haskell lets you create functions that have no name

plus 1000

Very useful for functions-that-are-used-once

Lambda: Creating Nameless Functions

Create nameless functions with lambda (just a \)

\ param -> body


For example, a function that returns 1 more than its input

\x -> x + 1


We can call it, just like any other function

ghci> (\x -> x + 1) 100
101

ghci> doTwice (\x -> x + 1) 100
102

Lambda: Creating Nameless Functions

Lambda-functions are just values ... so you can name them

plus42 = \x -> x + 42

Lambda: Creating Nameless Functions

Lambda-functions are just values ... so you can name them

In general, an old-school equation-style function definition

f x1 x2 ... xn = e 


is equivalent to the lambda-style definition

f = \x1 -> \x2 -> ... xn -> e 


which can be shortened to

f = \x1 x2 ... xn -> e 

Infix Operators and Sections

Infix Operators

To improve readability Haskell lets you use some functions as infix

  1. Any function whose name is surrounded in backticks

  2. Any function defined with parens

Infix Operators with Backticks

Instead of plus 2 10 you can write

ghci> 2 `plus` 10 
12

or, instead of clone "thirty" 3 you can say

ghci> "thirty" `clone` 3
["thirty", "thirty", "thirty"]

Infix Operators with Parentheses

For some heavily used functions, convenient to skip the ticks

-- What does this function do?
(++) []     ys = ys
(++) (x:xs) ys = x : (xs ++ ys)

which lets us write

ex2 = [1,2,3] ++ [4,5,6]

Quiz: What is the value of ex2 ?

Sections


To further improve readability, partially apply infix operators

ghci> doTwice (+1) 0
2

: the list cons operator, is also infix, so...

ex3 = doTwice (0:) [7]

Quiz: what is the value of ex3 ?

Recap: Higher Order Functions