Lecture #11, Nov. 01, 2004

28
Cse536 Functional Programming 1 06/14/22 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

description

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 - PowerPoint PPT Presentation

Transcript of Lecture #11, Nov. 01, 2004

Page 1: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

104/21/23

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

Page 2: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

204/21/23

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.

Page 3: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

304/21/23

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 defaultdefinition of (/=)

Page 4: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

404/21/23

Properties of a class definitionclass (Eq a) => Ord a 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.

Page 5: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

504/21/23

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)

Page 6: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

604/21/23

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

Page 7: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

704/21/23

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

Page 8: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

804/21/23

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)

Page 9: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

904/21/23

Num InstanceThen 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

Page 10: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1004/21/23

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

Page 11: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1104/21/23

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

Page 12: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1204/21/23

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?

Page 13: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1304/21/23

Full Definition of Ordclass (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

Page 14: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1404/21/23

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

Page 15: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1504/21/23

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?

Page 16: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1604/21/23

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

Page 17: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1704/21/23

Analyzeinstance

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 (==) ?

Page 18: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1804/21/23

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

Page 19: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

1904/21/23

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.

Page 20: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2004/21/23

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)))

Page 21: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2104/21/23

show can be defined in terms of shows

• showTree tree = showsTree tree “”

• Exercise: write the functionshowsList :: Show a => [a] -> String -> String

showsList [] s = ...

showsList (x:xs) s = ...

Page 22: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2204/21/23

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)

Page 23: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2304/21/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

Page 24: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2404/21/23

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

Page 25: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2504/21/23

Another Invariant exampleclass (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

Page 26: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2604/21/23

The fix point operatorfix :: (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)

Page 27: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2704/21/23

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

Page 28: Lecture #11,  Nov. 01,  2004

Cse536 Functional Programming

2804/21/23

Example usef 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