1 / 31

Lecture #6, Oct 13, 2004

Lecture #6, Oct 13, 2004. Reading Assignments Read chapter 5 of the Text Polymorphic and Higher-Order Functions Read chapter 6 of the Text Shapes III: Perimeters of Shapes Assignment #3 – Now in Assignments directory Assigned: Oct. 13, 2004

kyrene
Download Presentation

Lecture #6, Oct 13, 2004

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture #6, Oct 13, 2004 • Reading Assignments • Read chapter 5 of the Text Polymorphic and Higher-Order Functions • Read chapter 6 of the Text Shapes III: Perimeters of Shapes • Assignment #3 – Now in Assignments directory • Assigned: Oct. 13, 2004 • Due, in class: Wednesday, Oct. 20, 2004 • Today’s Topics • Polymorphic Functions • Polymorphic datatypes • Type Constructors define polymorphic Constructor functions • Recursive datatypes • Higher Order functions • Perimeters of Shapes

  2. Polymorphic Length len :: [a] -> Int len [] = 0 len (x:xs) = 1 + len xs • Polymorphic functions don’t “look at” their polymorphic arguments. • They use the same code now matter what the type of their polymorphic arguments. “a” is a type variable. It is lowercase to distinguish it from types, which are uppercase.

  3. Polymorphism • Consider: tag1 x = (1,x) ? :type tag1 tag1 :: a -> (Int,a) • Other functions have types like this consider (++) ? :type (++) (++) :: [a] -> [a] -> [a] ? :type ([1,2]++) ([1,2] ++) :: [Int] -> [Int] • What are some other polymorphic functions and their types? • id :: • reverse :: • head :: • tail :: • (:) ::

  4. Polymorphic data structures • Polymorphism originates from data structures that don’t care what kind of data they store. id :: a -> a -- The ultimate -- polymorphic function reverse :: [a] -> [a] -- lists tail :: [a] -> [a] head :: [a] -> a (:) :: a -> [a] -> [a] tag1 :: Num a => b -> (a,b) -- tuples • How do we define new data structures with “holes” that can be polymorphic?

  5. Parametric Type Constructors The type parameter to Option causes it’s constructors to be polymorphic • Polymorphic types data Option a = NONE | SOME a • Note NONE is a constant, SOME is a function • We can have: type example with that type Option Int SOME 3 Option String SOME "x" Option (Int,Bool) SOME (3,True) even Option (Option Int) • Give some examples with the type Option (Option Int)

  6. Why use Option? pos :: Eq a => a -> [a] -> Option Int pos a l = let find a [] n = NONE find a (x:xs) n = if a==x then SOME n else find a xs (n+1) in find a l 0 ? pos 4 [1,2,3,4,5] SOME 3 ? pos 4 [1,5,6,7] NONE • Option is a type constructor since it constructs new types from old ones.

  7. Types Constructors with multiple inputs data Pair a b = Pair(a,b) data Pair2 a b = Pair2 a b • In Haskell sometimes the Type constructor and the value constructor have the same name. ? :t Pair(2,"x") Pair (2,"x") :: Pair Int [Char] ? :t Pair ((),Pair (2,3)) Pair ((),Pair (2,3)) :: Pair () (Pair Int Int) • Domain of constructors - To use tuples or not? That is the question! ? :t Pair Pair :: (a,b) -> Pair a b ? :t Pair2 Pair2 :: a -> b -> Pair2 a b

  8. Recursive types Lists are predefined, but could be defined this way • Well known and loved lists data [a] = [] | a : [a] • You can define your own ! data Mylist a = Nil | Cons (a,Mylist a) • But be warned! The two are not the same type. ? :t Cons Cons :: (a,Mylist a) -> Mylist a ? Cons(3,2:[]) ERROR: Cannot derive instance in expression *** Expression : Cons (3,[ 2 ]) *** Required instance: Monad Mylist

  9. Recursive type constructors with multiple inputs data Twolist a b = Twonil | Acons (a,Twolist a b) | Bcons (b,Twolist a b) append2 Twonil ys = ys append2 (Acons(a,xs)) ys = Acons(a,append2 xs ys) append2 (Bcons(b,xs)) ys = Bcons(b,append2 xs ys) rev2 Twonil = Twonil rev2 (Acons(a,t)) = append2 (rev2 t) (Acons(a,Twonil)) rev2 (Bcons(b,t)) = append2 (rev2 t) (Bcons(b,Twonil)) ? :t rev2 rev2 :: Twolist a b -> Twolist a b ? append2 (Acons(2,Twonil))(Bcons(4,Twonil)) Acons (2,Bcons (4,Twonil))

  10. Recursive type constructors with 0 inputs data Nat = Zero | Succ Nat; • Is there any polymorphism here? Why not? • Write the addition function for Nat? add :: Nat -> Nat -> Nat add = • Write a fun from positive Int to Nat. toNat :: Int -> Nat ? toNat 3 Succ (Succ (Succ Zero)) toNat =

  11. Polymorphism from functions as arguments • Another source of polymorphism comes from functions which take functions as arguments. applyTwice f x = f(f x) Main> :t applyTwice applyTwice :: (a -> a) -> a -> a • What’s the type of z below? z f x y = (f x, f y)

  12. Polymorphism:Functions returned as values • Consider: k x = (\ y -> x) ? (k 3) 5 3 • What’s the type of K? • Another Example: compose f g = \ x -> f (g x) • What’s the type of compose ?

  13. Higher order functions abstract control • Higher order functions capture control patterns transList :: [Vertex] -> [Point] transList [] = [] transList (p:ps) = trans p : transList ps putCharList :: String -> [IO ()] putCharList [] = [] putCharList (c:cs) = putChar c : putChaList cs map f [] = [] map f (x:xs) = (f x):(map f xs)

  14. When do you define a higher order function? • Recognizing patterns is the key mysum [] = 0 mysum (x:xs) = (+)x (mysum xs) myprod [] = 1 myprod (x:xs) = (*)x (myprod xs) myand [] = True myand (x:xs) = (&&)x (myand xs) • Note the similarities in definition and in use ? mysum [1,2,3] 6 ? myprod [2,3,4] 24 ? myand [True, False] False

  15. Abstracting myfoldr ope [] = e myfoldr ope (x:xs) = op x (myfoldr ope xs) ? :t myfoldr myfoldr :: (a -> b -> b) -> b -> [a] -> b ? myfoldr (+) 0 [1,2,3] 6 ?

  16. Using foldr • Once we’ve captured a pattern we should use it! mysum = foldr (+) 0 myprod = foldr (*) 1 myand = foldr (&&) True • Study the definitions below. Define equivalent functions in terms of foldr. map f [] = [] map f (x:xs) = (f x):(map f xs) map f = foldr . . . append [] ys = ys append (x:xs) ys = x : (append xs ys) append xs ys = foldr . . .

  17. foldl • Let: x = [1,2,3,4] foldr :: (a -> b -> b) -> b -> [a] -> b foldr (+) e x = 1 + (2 + (3 + e)) foldl :: (b -> a -> b) -> b -> [a] -> b foldl (+) e x = (((e + 1) + 2) + 3) + 4 • Can you define foldl?

  18. Why foldl and foldr? • Grouping from the left or the right matters in some computations. • Consider the two defintions concat1 :: [[a]] -> [a] concat1 = foldr (++) [] concat2 :: [[a]] -> [a] concat2 = foldl (++) [] • Which is more efficient? concat1 [x,y,z] = x ++ (y ++ z) concat2 [x,y,z] = (x ++ y) ++ z

  19. Reverse rev [] = [] rev (x:xs) = (rev xs) ++ [x] • What’s the cost (in number of (:)’s) for rev [1,2,3,4]? • Can we do better? • Use an accumulating parameter rev2 [] ys = ys rev2 (x:xs) ys = . . . rev x = rev2 x [] • Can we write rev2 as a fold? • Which one do we use foldr or foldl?

  20. Artihmetic Sequences • Special syntax for computing lists with regular properties. [1 .. 6] = [1,2,3,4,5,6] [1,3 .. 9] = [1,3,5,7,9] • Infinite lists too! take 9 [1,3..] = [1,3,5,7,9,11,13,15,17] take 5 [5..] = [5,6,7,8,9]

  21. The perimeter of a Shape • To compute the perimeter we need a function with four equations (1 for each constructor of Shape) • The first three are easy … perimeter :: Shape -> Float perimeter (Rectangle s1 s2) = 2*(s1+s2) perimeter (RtTriangle s1 s2) = s1 + s2 + sqrt(s1^2+s2^2) perimeter (Polygon pts) = foldl (+) 0 (sides pts) • Provided we can compute a list of the length of the sides of a polygon. This shouldn’t be too difficult since we can compute the distance between two points with distBetween s1 s2 s1 s2

  22. Sides is easy recursively sides :: [Vertex] -> [Side] sides [] = [] sides (p:pts) = aux (p:pts) where aux (p1:p2:pts) = (distBetween p1 p2) : (aux (p2:pts)) aux (pn:[]) = distBetween pn p : [] -- aux [pn] = [distBetween pn p] • But can we do it as a seasoned functional programmer might do it?

  23. Visualize what’s happening B • The list of vertex, vs =[A,B,C,D,E] • distance between (A,B) (B,C) (C,D) (D,E) (E,A) • Can we compute these pairs as a list? [(A,B),(B,C),(C,D),(D,E),(E,A)] • Yes by zipping the following two lists: [A,B,C,D,E] [B,C,D,E,A] zip vs ((tail vs)++[head vs]) A C E D

  24. Second version of sides sides2 :: [Vertex] -> [Side] sides2 pts = zipWith distBetween pts (tail pts ++ [head pts]) In class exercise, define: zipWith zipWith f ...

  25. Perimeter of an Ellipse • The perimeter of an ellipse is given by the summation of an infinite series. For an ellipse with radii r1 and r2 p = 2pr1(1 - S si) where s1 = 1/4 e2 si+1 = si (2i-1)(2i-3) e2 for i>= 1 4i2 e = sqrt(r1* r1 - r2 * r2)/r1 Given si its is easy to compute the next value in the series s i+1

  26. Computing the series nextEl:: Float -> Float -> Float -> Float nextEl e s i = s*(2*i-1)*(2*i-3)*(e^2) / (4*i^2) • We want to compute [s1,s2,s3, …] • for fixed e aux s i = nextEl e s i [s1, aux s1 1, aux (aux s1 1) 2, aux (aux (aux s1 1) 2) 3, …] si+1 = si (2i-1)(2i-3) e2 4i2 Can we capture this pattern?

  27. Scanl (scan from the left) [s1, s2 = f s1 1, s3 = f s2 2 = f(f s1 1) 2, s4 = f s3 3 = f(f (f s1 1) 2) 3, …] scanl :: (a -> b -> b) -> b -> [a] -> [b] scanl f seed [] = seed : [] scanl f seed (x:xs) = seed : scanl f newseed xs where newseed = f x seed scanl aux s1 [1,2 ..]

  28. We get the following pattern s1 = 1/4 e2 s1 = 0.25 * ((r1^2 - r2^2) / r1) where r1 and r2 are the radii of the ellipse [s1, s2 = aux s1 1, s3 = aux s2 2, s4 = aux s3 3, …]

  29. e = sqrt (r1^2 - r2^2) / r1 = 0.699854 [s1 = 0.122449, s2 = 0.0112453, s3 = 0.00229496, s4 = 0.000614721, s5 = 0.000189685, …] Note how quickly the series gets real small ... r1 = 2.1 r2 = 1.5

  30. Putting it all together This is s1 perimeter (Ellipse r1 r2) | r1 > r2 = ellipsePerim r1 r2 | otherwise = ellipsePerim r2 r1 where ellipsePerim r1 r2 = let e = sqrt (r1^2 - r2^2) / r1 s = scanl aux (0.25*e^2) (map intToFloat [2..]) aux s i = nextEl e s i test x = x > epsilon sSum = foldl (+) 0 (takeWhile test s) in 2*r1*pi*(1 - sSum)

  31. Assignment #3, Also in the assignments web page Be sure and include a listing (1-2 pages) which shows how you tested your programs in the Hugs system. 1) Write a function "wordsL" such that (wordsL "This is a sentence.") returns ["This", "is","a","sentence."]. It breaks a string into a list of strings. It breaks the strings (and throws away the separators) at blanks ( ' ' ), tabs ( '\t' ), and newlines ( '\n' ). Hint: takeWhile and dropWhile are very useful. e.g. (takeWhile even [2,4,5,6,7]) => [2,4]. There is a function called words in the prelude that does exactly this. Write your own version. 2) Exercise 3.1 page 49 of the text 3) Use the IO monad to write a function when given two strings as input, opens a file with the first strings name, and copys it to another file, with the name of the second string. copy :: String -> String -> IO () . Be sure and test your function in the input you hand in. 4) Write a program "pal" which reads a string from the user, and then prints on the screen if that string is a palindrome. (A palindrome is a string which reads the same both forwards and backwards. For example "hah" and "abCba".) pal :: IO () 5) Using the primitive drawing functions of chapter 4 of the text, open a graphics window and draw a picture of a "house".

More Related