1 / 28

Lecture #11, Nov. 01, 2004

Lecture #11, Nov. 01, 2004. Special Guest lecture by Tom Harke Today’s Topics The Haskell Class system Instance declarations Inheritance and dependent classes Derived instances The Show class The Fix operator from homework # 5 Reading Assignment Chapter 12 - Qualified Types

talasi
Download Presentation

Lecture #11, Nov. 01, 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 #11, Nov. 01, 2004 • Special Guest lecture by Tom Harke • Today’s Topics • The Haskell Class system • Instance declarations • Inheritance and dependent classes • Derived instances • The Show class • The Fix operator from homework # 5 • Reading Assignment • Chapter 12 - Qualified Types • Appendix - A Tour of Haskell’s Standard Type Classes Sections 24.4 & 24.5 The Show and Read Class (pp 334-340) • Reminder - Mid-Term Exam Wednesday - next class meeting! • open book exam

  2. The Haskell Class System • Think of a Qualified type as a type with a Predicate • Types which meet those predicates have "extra" functionality. • A class definition defines the type of the "extra" functionality. • An instance declarations defines the "extra" functionality for a particular type.

  3. Example Class Definition class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x==y) class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a Note default definition of (/=)

  4. Properties of a class definition class (Eqa) => Orda where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a • Class name is capitalized, think of this as the name of a type predicate that qualifies the type being described. • Classes can depend on another class or in other words require another classes as a prerequisite • The methods of a class are functions whose type can depend upon the type being qualified • There can be more than one method. • The methods can be ordinary (prefix) functions or infix operators.

  5. First Example • Example: • The Class Eq • Concrete Types without arrows (functions -> ) support equality. • Assume basic equalities: int_eq, string_eq, bool_eq • Make the following tree like data types that represent arithmetic expressions, instances of class Eq data Aop = Add | Sub | Mult | Div data Aexp = Num Int | Exp (Aexp, Aop, Aexp)

  6. First define equality functions aop_eq Add Add = True aop_eq Sub Sub = True aop_eq Mult Mult = True aop_eq Div Div = True aop_eq _ _ = False aexp_eq (Num x) (Num y) = int_eq x y aexp_eq (Exp(e1,x,e2))(Exp(f1,y,f2)) = (aexp_eq e1 f1) && (aop_eq x y) && (aexp_eq e2 f2) aexp_eq _ _ = False

  7. Then make Instance Definitions • To make an instance instance Eq(Aop) where x == y = aop_eq x y x /= y = not(aop_eq x y ) instance Eq(Aexp) where x == y = aexp_eq x y x /= y = not(aexp_eq x y ) • Example use ? (Num 3) == (Num 5) False ? (Num 3) == (Num (5-2)) True

  8. Another Example: Num Complex • Make Complex numbers an instance of class Num. data Complex = C Float Float • An instance of Num, must first be an instance of Eq and Show and provide methods for (+), (-), and (*) (amongst others). First provide the numeric operators complex_add (C x y) (C a b) = C (x+a) (y+b) complex_sub (C x y) (C a b) = C (x-a) (y-b) complex_mult (C x y) (C a b) = C (x*a - y*b) (x*b + a*y)

  9. Num Instance Then make the instance declarations instance Eq(Complex) where (C x y) == (C a b) = x==a && y==b instance Show(Complex) where showsPrec = error "No show for complex" showList = error "No show for complex" instance Num(Complex) where x + y = complex_add x y x - y = complex_sub x y x * y = complex_mult x y • Note that the Show instance is quite imprecise, but this will cause an error only if it is ever used

  10. Full Num Class class (Eq a, Show a) => Num a where (+), (-), (*) :: a -> a -> a negate :: a -> a abs, signum :: a -> a fromInteger :: Integer -> a fromInt :: Int -> a x - y = x + negate y fromInt = fromIntegral

  11. Class Ord • The Class Ord is interesting for several reasons • It’s a dependant Class, so it uses inheritance Class Eq a => Ord a where ... • It makes extensive use of default method definitions • Example: Eq Tree => Ord Tree data Tree a = Leaf a | Branch (Tree a) (Tree a) • First make Tree an instance of Eq instance Eq a => Eq (Tree a) where (Leaf x) == (Leaf y) = x==y (Branch x y) == (Branch a b) = x==a && y==b _ == _ = False

  12. Make Tree an instance of Ord • First define a (<) and (<=) function for Tree Int instance (Ord a,Eq a) => Ord(Tree a) where (Leaf _) < (Branch _ _) = True (Leaf x) < (Leaf y) = x < y (Branch _ _) < (Leaf _) = False (Branch l1 r1) < (Branch l2 r2) = if l1==l2 then r1 < r2 else l1 < l2 t1 <= t2 = t1 < t2 || t1 == t2 is Eq a really necessary as a dependent type?

  13. Full Definition of Ord class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a compare x y | x==y = EQ | x<=y = LT | otherwise = GT x <= y = compare x y /= GT x < y = compare x y == LT x >= y = compare x y /= LT x > y = compare x y == GT max x y | x >= y = x | otherwise = y min x y | x <= y = x | otherwise = y An instance need only provide enough methods to define the others. Here compare would be enough or just <= plus Eq a

  14. A closer look. Classes for Type Constructors • How do classes work for type constructors like Tree and [-] • Consider: data Mylist a = Nil | Cons a (Mylist a) int_list_eq(Nil, Nil) = True int_list_eq(Cons x xs, Cons y ys) = (int_eq x y) && (int_list_eq(xs,ys)) int_list_eq (_, _) = False list_eq :: (a -> a -> Bool) -> (Mylist a,Mylist a) -> Bool list_eq f (Nil, Nil) = True list_eq f (Cons x xs, Cons y ys) = (f x y) && (list_eq f (xs, ys)) list_eq f (_, _) = False

  15. Classes for Type Constructors • The function list_eq motivates the following Dependent instance. instance Eq a => Eq(Mylist a) where Nil == Nil = True (Cons x xs) == (Cons y ys) = (x == y) && (xs == ys) _ == _ = False ? Nil == (Cons 2 Nil) False ? (Cons 2 Nil) == (Cons (3-1) Nil) True What type is (==) used at? What type is (==) used at?

  16. Think about this! • Consider : data Bush a = One a | Two (Bush a) (Bush a) | Many [Bush a] instance Eq a => Eq(Bush a) where (One x) == (One y) = (x == y) (Two x1 x2) == (Two y1 y2) = (x1 == y1) && (x2 == y2) (Many xs) == (Many ys) = (xs == ys) _ == _ = False ? Many [One 2] == Many [One 2, Two (One 3) (One 5)] False ? Many [One 3] == Many [One 3] True

  17. Analyze instance Eq a => Eq(Bush a) where (One x) == (One y) = (x == y) (Two x1 x2) == (Two y1 y2) = (x1 == y1) && (x2 == y2) (Many xs) == (Many ys) = (xs == ys) _ == _ = False • (==) :: a -> a -> Bool • (==) :: Bush a -> Bush a -> Bool • (==) :: Bush a -> Bush a -> Bool • (==) :: [ Bush a ] -> [ Bush a ] -> Bool • How do we get (==) ?

  18. The Class Show • Instances of the Class Show are those types that can be converted to character strings show :: Show a => a -> String • Example uses: show (2+2) ---> “4” show (not (3=4)) ---> “True” Using show and concatenation (++) “My name is” ++ show name ++ “I am” ++ show age ++ “years old” • (++) is right associative so this runs in linear time

  19. Show and Trees • If we try and define a show function for trees we lose this linear time property. Consider a simplification of Class Show (see the appendix for the real definition): Instance Show a => Show (Tree a) where show (Leaf x) = “(Leaf ” ++ show x ++ “)” show (Branch x y) = “(Branch” ++ show x ++ show y ++ “)” When we Show the left sub-tree x, and the right sub-tree y, we end re-concatenating the string returned by the “recursive” call.

  20. Restoring Linearity • Suppose we had a function shows shows :: Show a => a -> String -> String • And shows was part of the Show Class as well. Class Show a where show :: a -> String shows :: a -> String -> String • Where shows has an extra String argument • Think of this argument as an accumulating parameter, that holds all of the string printed so far. showsTree :: Show a => Tree a -> String -> String showsTree (Leaf x) s = “(Leaf ” ++ show x ++ “)” ++ s showsTree (Branch x y) s = “(Branch” ++ (showsTree x (showsTree y (“)” ++ s)))

  21. show can be defined in terms of shows • showTree tree = showsTree tree “” • Exercise: write the function showsList :: Show a => [a] -> String -> String showsList [] s = ... showsList (x:xs) s = ...

  22. Derived Instances • Some Classes are so useful and so simple to define, that we’d like the compiler to do it for us. • Example derivable Classes: • Eq • Ord • Show • Example Uses of deriving classes data Color = Red | Orange | Yellow | Green | Blue |Indigo | Violet deriving Show data Exp = Int Int | Plus Exp Exp | Minus Exp Exp deriving (Eq,Show)

  23. Type propagation in the Class System • Class information propagates from the use of functions with qualified types into the functions they are used to define: • Example: member x [] = False member x (z:zs) = if x==z then True else member x zs • Note that the type of (==) (==) :: Eq a => a -> a -> Bool has propagated into the type of member member :: Eq a => a -> [a] -> Bool

  24. Implicit invariants of Type Classes • When we define a type class (especially those with multiple methods) we often want some things to be true about the way the methods interact. • In Haskell we can’t make these invariants explicit • E.g. class Eq a where (==), (/=) :: a -> a -> Bool x /= y = not (x==y) Invariants a == b => b == a a === a a == b && b == c => a == c

  25. Another Invariant example class (Eq a) => Ord a where compare :: a -> a -> Ordering (<), (<=), (>=), (>) :: a -> a -> Bool max, min :: a -> a -> a • Invariants • Exactly one of the following is true for all x,y::a 1) x < y 2) x == y 3) x > y • Transitivity x <= y && y <= z => x <= z

  26. The fix point operator fix :: (a -> a) -> a fix f = f ( fix f ) • By unrolling the definition of fix we see fix f = f ( f ( fix f ) ) We get repeated application of f. In fact we get infinite repeated application of f • Instantiate the type of fix at (b -> c) . We get: fix :: ((b->c) -> (b->c)) -> (b -> c)

  27. Use the eta rule fix :: ((b->c) -> (b->c)) -> (b -> c) fix f :: b -> c -- for appropriate f We can eta-expand the definition of fix fix f n = f (fix f) n

  28. Example use f fact n = if n=0 then 1 else fact(n-1) * n note f is not recursive factorial n = fix f n fix f n = f (fix f) n = if n=0 then 1 else (fix f)(n-1) * n = if n=0 then 1 else f (fix f) (n-1) * n = if n=0 then 1 else if (n-1)=0 then 1 else (fix f) (n-2) * n

More Related