<<

REVISION:POLYMORPHIC USER-DEFINED LISTS

Polymorphic : ➜ We use a type variable in the data declaration

data List a = Nil | Cons a (List a)

Matching polymorphic operations: lengthList :: List a -> Int lengthList Nil = 0 lengthList (Cons _ xs) = 1 + lengthList xs

REVISION:POLYMORPHIC USER-DEFINED LISTS 1 REVISION:POLYMORPHIC USER-DEFINED LISTS

Polymorphic data structure: ➜ We use a type variable in the data declaration

data List a = Nil | Cons a (List a)

Matching polymorphic operations: lengthList :: List a -> Int lengthList Nil = 0 lengthList (Cons _ xs) = 1 + lengthList xs

REVISION:POLYMORPHIC USER-DEFINED LISTS 1-A OVERLOADING REVISITED

We know two ways in which type variables can be used: ➜ : lengthList :: List a -> Int

• Any type can be substituted for the type variable a • We can have List Int, List Float, List String, etc. ➜ Ad-hoc polymorphism (overloading): (+) :: Num a => a -> a -> a

• Only members of the Num are allowed for a • E.g., Int and Float are permitted, but String is not • Num a is called a type constraint

How do user-defined types and overloading interact?

OVERLOADING REVISITED 2 OVERLOADING REVISITED

We know two ways in which type variables can be used: ➜ Parametric polymorphism: lengthList :: List a -> Int

• Any type can be substituted for the type variable a • We can have List Int, List Float, List String, etc. ➜ Ad-hoc polymorphism (overloading): (+) :: Num a => a -> a -> a

• Only members of the type class Num are allowed for a • E.g., Int and Float are permitted, but String is not • Num a is called a type constraint

How do user-defined types and overloading interact?

OVERLOADING REVISITED 2-A OVERLOADING REVISITED

We know two ways in which type variables can be used: ➜ Parametric polymorphism: lengthList :: List a -> Int

• Any type can be substituted for the type variable a • We can have List Int, List Float, List String, etc. ➜ Ad-hoc polymorphism (overloading): (+) :: Num a => a -> a -> a

• Only members of the type class Num are allowed for a • E.g., Int and Float are permitted, but String is not • Num a is called a type constraint

How do user-defined types and overloading interact?

OVERLOADING REVISITED 2-B OVERLOADING REVISITED

We know two ways in which type variables can be used: ➜ Parametric polymorphism: lengthList :: List a -> Int

• Any type can be substituted for the type variable a • We can have List Int, List Float, List String, etc. ➜ Ad-hoc polymorphism (overloading): (+) :: Num a => a -> a -> a

• Only members of the type class Num are allowed for a • E.g., Int and Float are permitted, but String is not • Num a is called a type constraint

How do user-defined types and overloading interact?

OVERLOADING REVISITED 2-C OVERLOADING REVISITED

We know two ways in which type variables can be used: ➜ Parametric polymorphism: lengthList :: List a -> Int

• Any type can be substituted for the type variable a • We can have List Int, List Float, List String, etc. ➜ Ad-hoc polymorphism (overloading): (+) :: Num a => a -> a -> a

• Only members of the type class Num are allowed for a • E.g., Int and Float are permitted, but String is not • Num a is called a type constraint

How do user-defined types and overloading interact?

OVERLOADING REVISITED 2-D Type classes that we have encountered so far: ➜ A range of standard functions imposes type constraints on the types at which they are applied:

(+), (-), and so on require Num (==) and (/=) require Eq (>), (>=), and so on require Ord [a, b..c] requires Enum show and read require Show and Read ➜ By default, user-defined types do not belong to any type classes ➜ As a consequence, we cannot even apply functions, such as (==), to types, such as Day ✧

OVERLOADING REVISITED 3 Type classes that we have encountered so far: ➜ A range of standard functions imposes type constraints on the types at which they are applied:

(+), (-), and so on require Num (==) and (/=) require Eq (>), (>=), and so on require Ord [a, b..c] requires Enum show and read require Show and Read ➜ By default, user-defined types do not belong to any type classes ➜ As a consequence, we cannot even apply functions, such as (==), to types, such as Day ✧

OVERLOADING REVISITED 3-A Eq and Ord:: ➜ For simple equality tests ((==) and (/=)) Eq is sufficient ➜ For an ordering on values, Ord is also needed ➜ In a data definition, the keyword deriving introduces the requested type classes data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord) -- derive both ➜ Monday == Monday ⇒ True ➜ Monday < Wednesday ⇒ True ✧ ➜ Arguments of constructors must also belong to the type classes

OVERLOADING REVISITED 4 Eq and Ord:: ➜ For simple equality tests ((==) and (/=)) Eq is sufficient ➜ For an ordering on values, Ord is also needed ➜ In a data definition, the keyword deriving introduces the requested type classes data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord) -- derive both ➜ Monday == Monday ⇒ True ➜ Monday < Wednesday ⇒ True ✧ ➜ Arguments of constructors must also belong to the type classes

OVERLOADING REVISITED 4-A Eq and Ord:: ➜ For simple equality tests ((==) and (/=)) Eq is sufficient ➜ For an ordering on values, Ord is also needed ➜ In a data definition, the keyword deriving introduces the requested type classes data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord) -- derive both ➜ Monday == Monday ⇒ True ➜ Monday < Wednesday ⇒ True ✧ ➜ Arguments of constructors must also belong to the type classes

OVERLOADING REVISITED 4-B Eq and Ord:: ➜ For simple equality tests ((==) and (/=)) Eq is sufficient ➜ For an ordering on values, Ord is also needed ➜ In a data definition, the keyword deriving introduces the requested type classes data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord) -- derive both ➜ Monday == Monday ⇒ True ➜ Monday < Wednesday ⇒ True ✧ ➜ Arguments of constructors must also belong to the type classes

OVERLOADING REVISITED 4-C Enum: ➜ For the forms [a..b] and [a, b..c], we need Enum ✧ ➜ Can only be derived for enumeration types

data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Enum) ➜ [Monday..Friday] ⇒ [Monday, Tuesday, Wednesday, Thursday, Friday]

OVERLOADING REVISITED 5 Enum: ➜ For the forms [a..b] and [a, b..c], we need Enum ✧ ➜ Can only be derived for enumeration types

data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Enum) ➜ [Monday..Friday] ⇒ [Monday, Tuesday, Wednesday, Thursday, Friday]

OVERLOADING REVISITED 5-A Enum: ➜ For the forms [a..b] and [a, b..c], we need Enum ✧ ➜ Can only be derived for enumeration types

data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Enum) ➜ [Monday..Friday] ⇒ [Monday, Tuesday, Wednesday, Thursday, Friday]

OVERLOADING REVISITED 5-B Using the derived functions: ➜ Function that tests whether a Day is a working day:

isWorkingDay :: Day -> Bool isWorkingDay day = day `elem` [Monday..Friday]

➜ This requires both Enum and Eq ➜ Remember that elem :: Eq a => a -> [a] -> Bool

OVERLOADING REVISITED 6 Using the derived functions: ➜ Function that tests whether a Day is a working day:

isWorkingDay :: Day -> Bool isWorkingDay day = day `elem` [Monday..Friday]

➜ This requires both Enum and Eq ➜ Remember that elem :: Eq a => a -> [a] -> Bool

OVERLOADING REVISITED 6-A Using the derived functions: ➜ Function that tests whether a Day is a working day:

isWorkingDay :: Day -> Bool isWorkingDay day = day `elem` [Monday..Friday]

➜ This requires both Enum and Eq ➜ Remember that elem :: Eq a => a -> [a] -> Bool

OVERLOADING REVISITED 6-B Show and Read: We have show :: Show a => a -> String read :: Read a => String -> a

These are important because of print :: Show a => a -> IO () -- output to stdout readLn :: Read a => IO a -- read from stdin

➜ By deriving Show and Read, user-defined values can be • read from and written to • the console and files ✧

OVERLOADING REVISITED 7 Show and Read: We have show :: Show a => a -> String read :: Read a => String -> a

These are important because of print :: Show a => a -> IO () -- output to stdout readLn :: Read a => IO a -- read from stdin

➜ By deriving Show and Read, user-defined values can be • read from and written to • the console and files ✧

OVERLOADING REVISITED 7-A The Maze Example

OVERLOADING REVISITED 8