cse536 functional programming 1 6/10/2015 lecture #6, oct 13, 2004 reading assignments –read...
Post on 19-Dec-2015
216 views
TRANSCRIPT
Cse536 Functional Programming
104/18/23
Lecture #6, Oct 13, 2004• Reading Assignments
–Read chapter 5 of the TextPolymorphic and Higher-Order Functions
–Read chapter 6 of the TextShapes 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
Cse536 Functional Programming
204/18/23
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 islowercase to distinguish it
from types, which are uppercase.
Cse536 Functional Programming
304/18/23
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 :: – (:) ::
Cse536 Functional Programming
404/18/23
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?
Cse536 Functional Programming
504/18/23
Parametric Type Constructors• 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 3Option String SOME "x"Option (Int,Bool) SOME (3,True)
even Option (Option Int) • Give some examples with the type Option (Option Int)
The type parameter to Optioncauses it’s constructors to
be polymorphic
Cse536 Functional Programming
604/18/23
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.
Cse536 Functional Programming
704/18/23
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
Cse536 Functional Programming
804/18/23
Recursive types• 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
Lists are predefined, butcould be defined this way
Cse536 Functional Programming
904/18/23
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))
Cse536 Functional Programming
1004/18/23
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 =
Cse536 Functional Programming
1104/18/23
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)
Cse536 Functional Programming
1204/18/23
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 ?
Cse536 Functional Programming
1304/18/23
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)
Cse536 Functional Programming
1404/18/23
When do you define a higher order function?
• Recognizing patterns is the keymysum [] = 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
Cse536 Functional Programming
1504/18/23
Abstracting myfoldr op e [] = e
myfoldr op e (x:xs) =
op x (myfoldr op e xs)
? :t myfoldr
myfoldr :: (a -> b -> b) -> b -> [a] -> b
? myfoldr (+) 0 [1,2,3]
6
?
Cse536 Functional Programming
1604/18/23
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 . . .
Cse536 Functional Programming
1704/18/23
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?
Cse536 Functional Programming
1804/18/23
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
Cse536 Functional Programming
1904/18/23
Reverserev [] = []
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?
Cse536 Functional Programming
2004/18/23
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]
Cse536 Functional Programming
2104/18/23
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
Cse536 Functional Programming
2204/18/23
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?
Cse536 Functional Programming
2304/18/23
Visualize what’s happening• 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
B
C
DE
Cse536 Functional Programming
2404/18/23
Second version of sides
sides2 :: [Vertex] -> [Side]
sides2 pts = zipWith distBetween pts
(tail pts ++ [head pts])
In class exercise, define: zipWith
zipWith f ...
Cse536 Functional Programming
2504/18/23
• The perimeter of an ellipse is given by the summation of an infinite series. For an ellipse with radii r1 and r2
p = 2r1(1 - si)
where s1 = 1/4 e2
si+1 = si (2i-1)(2i-3) e2 for i>= 1
4i2
e = sqrt(r1* r
1 - r
2 * r
2)/r1
Given si its is easy to compute the next value in the series s
i+1
Perimeter of an Ellipse
Cse536 Functional Programming
2604/18/23
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 eaux 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 capturethis pattern?
Cse536 Functional Programming
2704/18/23
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 ..]
Cse536 Functional Programming
2804/18/23
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,
…]
Cse536 Functional Programming
2904/18/23
r2 = 1.5
r1 = 2.1
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 quicklythe series gets realsmall ...
Cse536 Functional Programming
3004/18/23
Putting it all together
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)
This is s1
Cse536 Functional Programming
3104/18/23
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".