Functional Programming
Recursion
H. Turgut Uyar
2013-2015
License
© 2013-2015 H. Turgut Uyar
You are free to:
Share – copy and redistribute the material in any medium or format
Ada...
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Infix - Prefix
functions infix when in backquotes
mod n 2
n ‘mod‘ 2
operators prefix when in parentheses
6 * 7
(*) 6 7
Infix - Prefix
functions infix when in backquotes
mod n 2
n ‘mod‘ 2
operators prefix when in parentheses
6 * 7
(*) 6 7
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Guards
writing conditional expressions can become complicated
guards: predicates to check cases
n :: t1 -> t2 -> ... -> tk...
Guard Example
maximum of three integers
maxThree :: Integer -> Integer -> Integer -> Integer
maxThree x y z
| x>=y && x>=z...
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Errors
errors can be reported using error
doesn’t change the type signature
example: reciprocal (multiplicative inverse)
r...
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Recursion Examples
greatest common divisor
gcd :: Integer -> Integer -> Integer
gcd x y = if y == 0 then x else gcd y (x ‘...
Recursion Examples
greatest common divisor
gcd :: Integer -> Integer -> Integer
gcd x y = if y == 0 then x else gcd y (x ‘...
Stack Frame Example
gcd x y = if y == 0 then x else gcd y (x ‘mod‘ y)
gcd 9702 945
~> gcd 945 252
~> gcd 252 189
~> gcd 18...
Stack Frame Example
fac n
| n < 0 = error "negative parameter"
| n == 0 = 1
| otherwise = n * fac (n - 1)
fac 4
~> 4 * fac...
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Tail Recursion
if the result of the recursive call is also the result of the caller,
then the function is said to be tail ...
Tail Recursion
if the result of the recursive call is also the result of the caller,
then the function is said to be tail ...
Stack Frame Example
gcd x y = if y == 0 then x else gcd y (x ‘mod‘ y)
gcd 9702 945
~> gcd 945 252
~> gcd 252 189
~> gcd 18...
Tail Recursion
to rearrange a function to be tail recursive:
define a helper function that takes an accumulator
base case:...
Tail Recursion Example
tail recursive factorial
facIter :: Integer -> Integer -> Integer
facIter acc n
| n < 0 = error "ne...
Stack Frame Example
facIter acc n
| n < 0 = error "negative parameter"
| n == 0 = acc
| otherwise = facIter (acc * n) (n -...
Tail Recursion Example
helper function can be local
negativity check only once
fac :: Integer -> Integer
fac n
| n < 0 = e...
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Tree Recursion
Fibonacci sequence
fibn =



1 if n = 1
1 if n = 2
fibn−2 + fibn−1 if n > 2
fib :: Integer -> Integer
...
Stack Frame Example
Topics
1 Functions
Infix - Prefix
Guards
Errors
2 Recursion
Primitive Recursion
Tail Recursion
Tree Recursion
Examples
Exponentiation
pow :: Integer -> Integer -> Integer
pow x y
| y == 0 = 1
| otherwise = x * pow x (y - 1)
use the following...
Exponentiation
pow :: Integer -> Integer -> Integer
pow x y
| y == 0 = 1
| otherwise = x * pow x (y - 1)
use the following...
Fast Exponentiation
pow :: Integer -> Integer -> Integer
pow x y
| y == 0 = 1
| even y = sqr (pow x (y ‘div‘ 2))
| otherwi...
Square Roots with Newton’s Method
start with an initial guess y (say y = 1)
repeatedly improve the guess by taking the mea...
Square Roots with Newton’s Method
newton :: Float -> Float -> Float
newton guess x
| isGoodEnough guess x = guess
| otherw...
Square Roots with Newton’s Method
newton :: Float -> Float -> Float
newton guess x
| isGoodEnough guess x = guess
| otherw...
Square Roots with Newton’s Method
newton :: Float -> Float -> Float
newton guess x
| isGoodEnough guess x = guess
| otherw...
Square Roots with Newton’s Method
newton :: Float -> Float -> Float
newton guess x
| isGoodEnough guess x = guess
| otherw...
Square Roots with Newton’s Method
sqrt :: Float -> Float
sqrt x = newton 1.0 x
where
newton :: Float -> Float -> Float
new...
Square Roots with Newton’s Method
doesn’t work with too small and too large numbers (why?)
isGoodEnough guess x’ =
(abs (g...
Square Roots with Newton’s Method
no need to pass x around, it’s already in scope
sqrt x = newton 1.0
where
newton :: Floa...
References
Required Reading: Thompson
Chapter 3: Basic types and definitions
Chapter 4: Designing and writing programs
Upcoming SlideShare
Loading in...5
×

Functional Programming - Recursion

360

Published on

Recursion, tail recursion.

Published in: Education, Technology
0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
360
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
5
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Functional Programming - Recursion

  1. 1. Functional Programming Recursion H. Turgut Uyar 2013-2015
  2. 2. License © 2013-2015 H. Turgut Uyar You are free to: Share – copy and redistribute the material in any medium or format Adapt – remix, transform, and build upon the material Under the following terms: Attribution – You must give appropriate credit, provide a link to the license, and indicate if changes were made. NonCommercial – You may not use the material for commercial purposes. ShareAlike – If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. For more information: https://creativecommons.org/licenses/by-nc-sa/4.0/ Read the full license: https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode
  3. 3. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  4. 4. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  5. 5. Infix - Prefix functions infix when in backquotes mod n 2 n ‘mod‘ 2 operators prefix when in parentheses 6 * 7 (*) 6 7
  6. 6. Infix - Prefix functions infix when in backquotes mod n 2 n ‘mod‘ 2 operators prefix when in parentheses 6 * 7 (*) 6 7
  7. 7. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  8. 8. Guards writing conditional expressions can become complicated guards: predicates to check cases n :: t1 -> t2 -> ... -> tk -> t n x1 x2 ... xk | p1 = e1 | p2 = e2 ... | otherwise = e function result is the expression for the first satisfied predicate
  9. 9. Guard Example maximum of three integers maxThree :: Integer -> Integer -> Integer -> Integer maxThree x y z | x>=y && x>=z = x | y>=z = y | otherwise = z
  10. 10. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  11. 11. Errors errors can be reported using error doesn’t change the type signature example: reciprocal (multiplicative inverse) reciprocal :: Float -> Float reciprocal x | x == 0 = error "division by zero" | otherwise = 1.0 / x
  12. 12. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  13. 13. Recursion Examples greatest common divisor gcd :: Integer -> Integer -> Integer gcd x y = if y == 0 then x else gcd y (x ‘mod‘ y) factorial fac :: Integer -> Integer fac n | n < 0 = error "negative parameter" | n == 0 = 1 | otherwise = n * fac (n - 1)
  14. 14. Recursion Examples greatest common divisor gcd :: Integer -> Integer -> Integer gcd x y = if y == 0 then x else gcd y (x ‘mod‘ y) factorial fac :: Integer -> Integer fac n | n < 0 = error "negative parameter" | n == 0 = 1 | otherwise = n * fac (n - 1)
  15. 15. Stack Frame Example gcd x y = if y == 0 then x else gcd y (x ‘mod‘ y) gcd 9702 945 ~> gcd 945 252 ~> gcd 252 189 ~> gcd 189 63 ~> gcd 63 0 ~> 63 ~> 63 ~> 63 ~> 63 ~> 63
  16. 16. Stack Frame Example fac n | n < 0 = error "negative parameter" | n == 0 = 1 | otherwise = n * fac (n - 1) fac 4 ~> 4 * fac 3 ~> 3 * fac 2 ~> 2 * fac 1 ~> 1 * fac 0 ~> 1 ~> 1 ~> 2 ~> 6 ~> 24
  17. 17. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  18. 18. Tail Recursion if the result of the recursive call is also the result of the caller, then the function is said to be tail recursive the recursive function call is the last action: nothing left for the caller to do no need to keep the stack frame around: reuse the frame of the caller
  19. 19. Tail Recursion if the result of the recursive call is also the result of the caller, then the function is said to be tail recursive the recursive function call is the last action: nothing left for the caller to do no need to keep the stack frame around: reuse the frame of the caller
  20. 20. Stack Frame Example gcd x y = if y == 0 then x else gcd y (x ‘mod‘ y) gcd 9702 945 ~> gcd 945 252 ~> gcd 252 189 ~> gcd 189 63 ~> gcd 63 0 ~> 63
  21. 21. Tail Recursion to rearrange a function to be tail recursive: define a helper function that takes an accumulator base case: return accumulator recursive case: make recursive call with new accumulator value
  22. 22. Tail Recursion Example tail recursive factorial facIter :: Integer -> Integer -> Integer facIter acc n | n < 0 = error "negative parameter" | n == 0 = acc | otherwise = facIter (acc * n) (n - 1) fac :: Integer -> Integer fac n = facIter 1 n
  23. 23. Stack Frame Example facIter acc n | n < 0 = error "negative parameter" | n == 0 = acc | otherwise = facIter (acc * n) (n - 1) fac 4 ~> facIter 1 4 ~> facIter 4 3 ~> facIter 12 2 ~> facIter 24 1 ~> facIter 24 0 ~> 24 ~> 24
  24. 24. Tail Recursion Example helper function can be local negativity check only once fac :: Integer -> Integer fac n | n < 0 = error "negative parameter" | otherwise = facIter 1 n where facIter :: Integer -> Integer -> Integer facIter acc n’ | n’ == 0 = acc | otherwise = facIter (acc * n’) (n’ - 1)
  25. 25. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  26. 26. Tree Recursion Fibonacci sequence fibn =    1 if n = 1 1 if n = 2 fibn−2 + fibn−1 if n > 2 fib :: Integer -> Integer fib n | n == 1 = 1 | n == 2 = 1 | otherwise = fib (n - 2) + fib (n - 1)
  27. 27. Stack Frame Example
  28. 28. Topics 1 Functions Infix - Prefix Guards Errors 2 Recursion Primitive Recursion Tail Recursion Tree Recursion Examples
  29. 29. Exponentiation pow :: Integer -> Integer -> Integer pow x y | y == 0 = 1 | otherwise = x * pow x (y - 1) use the following definition: xy =    1 if y = 0 (xy/2 ) 2 if y is even x · xy−1 if y is odd
  30. 30. Exponentiation pow :: Integer -> Integer -> Integer pow x y | y == 0 = 1 | otherwise = x * pow x (y - 1) use the following definition: xy =    1 if y = 0 (xy/2 ) 2 if y is even x · xy−1 if y is odd
  31. 31. Fast Exponentiation pow :: Integer -> Integer -> Integer pow x y | y == 0 = 1 | even y = sqr (pow x (y ‘div‘ 2)) | otherwise = x * pow x (y - 1) where sqr :: Integer -> Integer sqr n = n * n
  32. 32. Square Roots with Newton’s Method start with an initial guess y (say y = 1) repeatedly improve the guess by taking the mean of y and x/y until the guess is good enough ( √ x · √ x = x) example: √ 2 y x/y next guess 1 2 / 1 = 2 1.5 1.5 2 / 1.5 = 1.333 1.4167 1.4167 2 / 1.4167 = 1.4118 1.4142 1.4142 ... ...
  33. 33. Square Roots with Newton’s Method newton :: Float -> Float -> Float newton guess x | isGoodEnough guess x = guess | otherwise = newton (improve guess x) x isGoodEnough :: Float -> Float -> Bool isGoodEnough guess x = abs (guess*guess - x) < 0.001 improve :: Float -> Float -> Float improve guess x = (guess + x/guess) / 2.0 sqrt :: Float -> Float sqrt x = newton 1.0 x
  34. 34. Square Roots with Newton’s Method newton :: Float -> Float -> Float newton guess x | isGoodEnough guess x = guess | otherwise = newton (improve guess x) x isGoodEnough :: Float -> Float -> Bool isGoodEnough guess x = abs (guess*guess - x) < 0.001 improve :: Float -> Float -> Float improve guess x = (guess + x/guess) / 2.0 sqrt :: Float -> Float sqrt x = newton 1.0 x
  35. 35. Square Roots with Newton’s Method newton :: Float -> Float -> Float newton guess x | isGoodEnough guess x = guess | otherwise = newton (improve guess x) x isGoodEnough :: Float -> Float -> Bool isGoodEnough guess x = abs (guess*guess - x) < 0.001 improve :: Float -> Float -> Float improve guess x = (guess + x/guess) / 2.0 sqrt :: Float -> Float sqrt x = newton 1.0 x
  36. 36. Square Roots with Newton’s Method newton :: Float -> Float -> Float newton guess x | isGoodEnough guess x = guess | otherwise = newton (improve guess x) x isGoodEnough :: Float -> Float -> Bool isGoodEnough guess x = abs (guess*guess - x) < 0.001 improve :: Float -> Float -> Float improve guess x = (guess + x/guess) / 2.0 sqrt :: Float -> Float sqrt x = newton 1.0 x
  37. 37. Square Roots with Newton’s Method sqrt :: Float -> Float sqrt x = newton 1.0 x where newton :: Float -> Float -> Float newton guess x’ | isGoodEnough guess x’ = guess | otherwise = newton (improve guess x’) x isGoodEnough :: Float -> Float -> Bool isGoodEnough guess x’ = abs (guess*guess - x’) < 0.001 improve :: Float -> Float -> Float improve guess x’ = (guess + x’/guess) / 2.0
  38. 38. Square Roots with Newton’s Method doesn’t work with too small and too large numbers (why?) isGoodEnough guess x’ = (abs (guess*guess - x’)) / x’ < 0.001
  39. 39. Square Roots with Newton’s Method no need to pass x around, it’s already in scope sqrt x = newton 1.0 where newton :: Float -> Float newton guess | isGoodEnough guess = guess | otherwise = newton (improve guess) isGoodEnough :: Float -> Bool isGoodEnough guess = (abs (guess*guess - x)) / x < 0.001 improve :: Float -> Float improve guess = (guess + x/guess) / 2.0
  40. 40. References Required Reading: Thompson Chapter 3: Basic types and definitions Chapter 4: Designing and writing programs
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×