Download presentation
Presentation is loading. Please wait.
Published byAri Hartono Modified over 5 years ago
1
Computer Science 312 Making choices Tail Recursion
Local contexts with where clauses Dealing with Errors Modules, Imports, Exports 1
2
Making Choices in Haskell
Use a set of function clauses, where pattern matching selects the option (factorial, fibonacci, etc.) factorial :: Integer -> Integer factorial 1 = 1 factorial n = n * factorial (n – 1) fibonacci:: Integer -> Integer fibonacci 1 = 1 fibonnaci 2 = 1 fibonacci n = fibonacci (n – 1) + fibonacci (n – 2)
3
Making Choices in Haskell
Simple function clauses will not work in the cases of functions like max, min, and sum, where the option depends on an explicit condition Prelude> max 3 4 4 Prelude> sum 1 4 10
4
Use a Function Guard Indentation is significant!
<function name> <parameters> | <Boolean expression-1> = <expression-1> … | <Boolean expression-n> = <expression-n> | otherwise = <default expression> myMax :: Ord a => a -> a -> Bool myMax x y | x > y = x | otherwise = y sum :: Integer -> Integer -> Integer sum lower upper | lower == upper = lower | otherwise = lower + sum (lower + 1) upper Indentation is significant!
5
Or Use an if-else Expression
<function name> <parameters> = if <Boolean expression-1> then <expression-1> … else if <Boolean expression-n> then <expression-n> else <default expression> myMax :: Ord a => a -> a -> Bool myMax x y = if x > y then x else y Syntactic sugar for function guards
6
Which Form to Prefer? factorial :: Integer -> Integer
factorial n = n * factorial (n – 1) factorial :: Integer -> Integer factorial n | n == 1 = 1 | otherwise = n * factorial (n – 1) factorial :: Integer -> Integer factorial n = if n == 1 then 1 else n * factorial (n – 1)
7
The case Expression interpretCommand :: Char -> String interpretCommand letter = case toUpper letter of 'N' -> newFile 'O' -> openFile 'S' -> saveFile 'Q' -> quitProgram _ -> handleError Like a switch statement in C or Java, but returns a value The _ symbol is a wildcard that matches any pattern
8
How Costly Is Recursion?
factorial :: Integer -> Integer factorial 1 = 1 factorial n = n * factorial (n – 1) fib:: Integer -> Integer fib 1 = 1 fib 2 = 1 fib n = fib (n – 1) + fib (n – 2) Factorial is O(n) in running time and memory Fibonacci is O(kn) in running time and O(logn) in memory The growth of memory is due to cells for each function call pushed onto the runtime stack
9
Tail Recursion factorial :: Integer -> Integer factorial 1 = 1 factorial n = n * factorial (n – 1) tailFactorial :: Integer -> Integer -> Integer tailFactorial 1 result = result tailFactorial n result = tailFactorial (n – 1) (n * result) In tail recursion, there is no work remaining to be done after a recursive call The compiler can translate this to a loop with a single record for state variables on the stack
10
Tracing the Two Versions
factorial 3 -> 3 * factorial 2 -> 2 * factorial 1 -> <- 1 <- 2 <- 6 tailFactorial 3 1 -> tailFactorial 2 3 -> tailFactorial 1 6 -> <- 6
11
Maintain the Interface with a Helper
factorial :: Integer -> Integer factorial n = tailFactorial n 1 tailFactorial :: Integer -> Integer -> Integer tailFactorial 1 result = result tailFactorial n result = tailFactorial (n – 1) (result * n)
12
Nest the Helper in a where Clause
factorial :: Integer -> Integer factorial n = tailFactorial n 1 where tailFactorial :: Integer -> Integer -> Integer tailFactorial 1 result = result tailFactorial n result = tailFactorial (n – 1) (result * n) If a function is just a helper for another function, you can define it locally within a where clause The scope of the where is determined by indentation
13
Nest Function in a where Clause
factorial :: Integer -> Integer factorial n = tailFactorial n 1 where tailFactorial :: Integer -> Integer -> Integer tailFactorial 1 result = result tailFactorial n result = tailFactorial (n – 1) (result * n) fib :: Integer -> Integer fib n = tailFib 1 0 n where tailFib:: Integer -> Integer -> Integer -> Integer tailFib a b 1 = a tailFib a b n = tailFib (a + b) a (n – 1) Both functions are now linear in running time and constant in memory usage
14
Dealing with Errors factorial :: Integer -> Integer factorial 0 = 1 factorial n | n < 0 = error "Argument n must be >= 0" | otherwise = n * factorial (n – 1) The error function halts the program with an error message
15
Modules Prelude – the standard module, always available
Data – organizes many data types under submodules Data.Char – character and text processing functions Data.Array – array processing functions Module names are capitalized
16
Full Imports Like from math import * Prelude> import Data.Char
Prelude Data.Char> isLetter('K') True Prelude Data.Char> isLower('K') False Prelude Data.Char> digitToInt('9') 9 Prelude Data.Char> ord('9') 57 Prelude Data.Char> chr(57) '9' Like from math import *
17
Partial Imports Like from math import sqrt, etc.
Prelude> import Data.Char (isLetter, isLower, digitToInt, ord) Prelude Data.Char> isLetter('K') True Prelude Data.Char> isLower('K') False Prelude Data.Char> digitToInt('9') 9 Prelude Data.Char> ord('9') 57 Prelude Data.Char> chr(57) '9' Like from math import sqrt, etc. Avoids name conflicts with other functions
18
Qualified Imports – The Full Slate
Prelude> import qualified Data.Char Prelude Data.Char> Data.Char.isLetter('K') True Prelude Data.Char> Data.Char.isLower('K') False Prelude Data.Char> Data.Char.digitToInt('9') 9 Prelude Data.Char> Data.Char.ord('9') 57 Prelude Data.Char> Data.Char.chr(57) '9' Like import math Avoids name conflicts with these and other functions
19
Qualified Imports – A Subset
Prelude> import qualified Data.Char (isLetter, isLower, digitToInt, ord) Prelude Data.Char> Data.Char.isLetter('K') True Prelude Data.Char> Data.Char.isLower('K') False Prelude Data.Char> Data.Char.digitToInt('9') 9 Prelude Data.Char> Data.Char.ord('9') 57 Prelude Data.Char> Data.Char.chr(57) '9' Avoids name conflicts with just these functions, And the others are not imported at all
20
Unrestricted Exports {- File: NewMath.hs Author: Ken Lambert Purpose: provides some simple math functions -} module NewMath where factorial :: Integer -> Integer factorial n = tailFactorial n 1 tailFactorial :: Integer -> Integer -> Integer tailFactorial 1 result = result tailFactorial n result = tailFactorial (n – 1) (result * n) Both factorial and tailFactorial are visible to importers
21
Restricted Exports {- File: NewMath.hs Author: Ken Lambert Purpose: provides some simple math functions -} module NewMath (factorial) where factorial :: Integer -> Integer factorial n = tailFactorial n 1 tailFactorial :: Integer -> Integer -> Integer tailFactorial 1 result = result tailFactorial n result = tailFactorial (n – 1) (result * n) Now the helper function tailFactorial is hidden from importers
22
For next time Introduction to lists, strings and tuples
Homework assignment #1 is available on Sakai!
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.