160 likes | 313 Views
Programming Paradigms. CPSC 449 Week 4 Prepared by : Mona Hosseinkhani , Arash Afshar Winter 2014. Department of Computer Science, University of Calgary. Pattern matching vs. guards in functions. An example function using guards mystery :: Integer -> Integer -> Integer mystery x y
E N D
Programming Paradigms CPSC 449 Week 4 Prepared by : Mona Hosseinkhani, ArashAfshar Winter 2014 Department of Computer Science, University of Calgary
Pattern matching vs. guards in functions • An example function using guards mystery :: Integer -> Integer -> Integer mystery x y | x==0 = y | otherwise = x • Same function using pattern matching(by two equations) mystery' :: Integer -> Integer -> Integer mystery' 0 y = y mystery' x _ = x • Equations are applied sequentially
Patterns and parentheses Always parenthesized patterns and constructors • example: f x:xs = (f x):xs and not as f (x:xs) • function applications bind more tightly than any other operations
The case construction • So far: pattern match over the arguments of functions • Case: pattern match over other values • example: Return the first digit in a string. firstDigit :: String -> Char firstDigitst = case (digits st) of [] -> '\0' (x:_) -> x where digits :: String -> Stringdigits st = [ ch | ch<-st , isDigitch] • case e of p1 -> e1 p2 -> e2 … pk -> ek
Testing re-implemented functions using QuickCheck • Suppose we re-implement a function like sum which is implemented in the Prelude • Requirements: • Hide the “sum definition in Prelude” when importing Prelude import Prelude hiding (…,sum,…) • Test our re-implemented sum against the original sum by: import qualified Prelude
Testing re-implemented functions using QuickCheck • Putting it together: module Chapter7 where import Prelude hiding (…,sum,…) import qualified Prelude import Test.QuickCheck sum = … our definition … prop_sum :: [Integer] -> Bool prop_sumxs = sum xs == Prelude.sumxs • This also can be used when we have two different implementations of a particular function.
Finding primitive recursive definitions • Given the value of fun xs, how could we define fun (x:xs) from it? • example: • Suppose you have the function “:” a->[a]->[a] (add a single element to the front of a list) • [2,3,4] ++ [9,8] = [2,3,4,9,8] • 2 : ([3,4] ++ [9,8]) • How we can define “++” [a]->[a]->[a] from “:”?(Join two list together) (++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x:(xs++ys)
Finding primitive recursive definitions • More examples: • Testingwhethersomething is a member of a list elem' :: Integer -> [Integer] -> Bool elem' x [] = False elem' x (y:ys) = (x==y) || (elem' x ys) • To double every element of an integer list doubleAll :: [Integer] -> [Integer] doubleAllxs = [ 2*x | x<-xs] doubleAll' [] = [] doubleAll' (x:xs) = 2*x : doubleAll' xs
Finding primitive recursive definitions • To select the even elements from an integer list selectEven :: [Integer] -> [Integer] selectEvenxs = [ x | x<-xs , isEven x ] selectEven' [] = [] selectEven' (x:xs) | isEven x = x : selectEven' xs | otherwise = selectEven' xs
General recursions over lists • A general recursive function . . . • may have more than one base case • may have different arguments for different recursive calls • arguments to recursive calls may not be strictly smaller than arguments to the function itself • may recurs on multiple arguments
General recursions over lists • More examples: • Zipping together two lists. zip :: [a] -> [b] -> [(a,b)] zip (x:xs) (y:ys) = (x,y) : zip xsys zip (x:xs) [] = [] zip [] zs = [] • Recurring on both arguments • Taking a given number of elements from a list take :: Int -> [a] -> [a] take 0 _ = [] take _ [] = [] take n (x:xs) | n>0 = x : take (n-1) xs take _ _ = error "PreludeList.take: negative argument” • Recurring on an integer and a list
Example: Text Processing • How to justify a paragraph • Bottom-up vs. Top-down approach • [Char] Words Lines • An input file in haskell can be treated as a string of characters. • The `whitespace' characters. whitespace = ['\n','\t',’ ‘] • Get a word from the front of a string. getWord :: String -> String getWord [] = [] getWord (x:xs) | elem x whitespace = [] | otherwise = x : getWordxs
Example: Text Processing • In a similar way, the first word of a string can be dropped. dropWord :: String -> String dropWord [] = [] dropWord (x:xs) | elem x whitespace = (x:xs) | otherwise = dropWordxs • To remove the whitespace character(s) from the front of a string. dropSpace :: String -> String dropSpace [] = [] dropSpace (x:xs) | elem x whitespace = dropSpacexs | otherwise = (x:xs)
Example: Text Processing • Splitting a string into words. type Word = String splitWords :: String -> [Word] splitWordsst = split (dropSpacest) split :: String -> [String] split [] = [] split st = (getWordst) : split (dropSpace (dropWordst)) • Getting a line from a list of words. type Line = [Word] getLine :: Int -> [Word] -> Line getLinelen [] = [] getLinelen (w:ws) | length w <= len = w : restOfLine | otherwise = [] where newlen = len - (length w + 1) restOfLine = getLinenewlenws
Example: Text Processing • Dropping the first line from a list of words. • dropLine :: Int -> [Word] -> Line • Splitting into lines splitLines :: [Word] -> [Line] splitLines [] = [] splitLinesws = getLinelineLenws: splitLines (dropLinelineLenws) • To fill a text string into lines, we write fill :: String -> [Line] fill = splitLines . splitWords
Question hossem<at>ucalgary.ca