From b22ec6de8428e540da79a6dffcb316542bf84fff Mon Sep 17 00:00:00 2001
From: Nadia Polikarpova Type Classes: Outline
@@ -497,7 +497,7 @@ Type Classes: Outline
@@ -552,16 +552,43 @@ The
Ord
TypeclassThe type class Ord
is for totally ordered values:
class Eq a => Ord a where
+ (<) :: a -> a -> Bool
+ (<=) :: a -> a -> Bool
+ (>) :: a -> a -> Bool
+ (>=) :: a -> a -> Bool
For example:
+> 2 < 3
+ λTrue
+
+> "cat" < "dog"
+ λTrue
+
Note Eq a =>
in the class definition!
A type T
is an instance of Ord
if
T
is also an instance of Eq
, and
+
+
+
+
+
Num
Type ClassThe type class Num
requires that instances define a bunch of arithmetic operations
class Num a where
- (+) :: a -> a -> a
- (-) :: a -> a -> a
- (*) :: a -> a -> a
- negate :: a -> a
- abs :: a -> a
- signum :: a -> a
- fromInteger :: Integer -> a
class Num a where
+ (+) :: a -> a -> a
+ (-) :: a -> a -> a
+ (*) :: a -> a -> a
+ negate :: a -> a
+ abs :: a -> a
+ signum :: a -> a
+ fromInteger :: Integer -> a
@@ -570,49 +597,80 @@
The Show
Type Class
The type class Show
requires that instances be convertible to String
class Show a where
- show :: a -> String
class Show a where
+ show :: a -> String
Indeed, we can test this on different (built-in) types
-> show 2
- λ"2"
-
-> show 3.14
- λ"3.14"
-
-> show (1, "two", ([],[],[]))
- λ"(1,\"two\",([],[],[]))"
> show 2
+ λ"2"
+
+> show 3.14
+ λ"3.14"
+
+> show (1, "two", ([],[],[]))
+ λ"(1,\"two\",([],[],[]))"
+
+
+
+
Ord
TypeclassThe type class Ord
is for totally ordered values:
class Eq a => Ord a where
- (<) :: a -> a -> Bool
- (<=) :: a -> a -> Bool
- (>) :: a -> a -> Bool
- (>=) :: a -> a -> Bool
For example:
-> 2 < 3
- λTrue
-
-> "cat" < "dog"
- λTrue
Read
Typeclass-- Not the actual definition, but almost:
+class Read a where
+ read :: String -> a
Read
is the opposite of Show
It requires that every instance T
can parse a string and turn it into T
Just like with Show
, most standard type are instances of Read
:
Int
, Integer
, Double
, Char
, Bool
, etc
+
+
+
+
+
+
+
Note Eq a =>
in the class definition!
A type T
is an instance of Ord
if
T
is also an instance of Eq
, andWhat does the expression read "2"
evaluate to?
(A) Type error
+(B) "2"
(C) 2
(D) 2.0
(E) Run-time error
+
+
+
+
+
+
Haskell is foxed!
+read
functions to run!Did we want an Int
or a Double
or maybe something else altogether?
+
Thus, here an explicit type annotation is needed to tell Haskell +what to convert the string to:
+> (read "2") :: Int
+ λ2
+
+> (read "2") :: Float
+ λ2.0
+
+> (read "2") :: String
+ λ???
Note the different results due to the different types.
@@ -642,7 +700,7 @@
@@ -657,19 +715,19 @@
Let’s create a new datatype:
-data Color = Red | Green
data Color = Red | Green
and play with it in GHCi:
-> let col = Red
- λ> :type col
- λx :: Color
> let col = Red
+ λ> :type col
+ λx :: Color
So far, so good… but we cannot view them!
-> col
- λ
-<interactive>:1:0:
-No instance for (Show Color)
- of `print' at <interactive>:1:0
- arising from a use Possible fix: add an instance declaration for (Show Color)
- In a stmt of a 'do' expression: print it
> col
+ λ
+<interactive>:1:0:
+No instance for (Show Color)
+ of `print' at <interactive>:1:0
+ arising from a use Possible fix: add an instance declaration for (Show Color)
+ In a stmt of a 'do' expression: print it
Why is this happening?
@@ -687,14 +745,14 @@
We also cannot compare colors!
-> col == Green
- λ
-<interactive>:1:0:
-No instance for (Eq Color)
- of `==' at <interactive>:1:0-5
- arising from a use Possible fix: add an instance declaration for (Eq Color)
- In the expression: col == Green
- In the definition of `it': it = col == Green
> col == Green
+ λ
+<interactive>:1:0:
+No instance for (Eq Color)
+ of `==' at <interactive>:1:0-5
+ arising from a use Possible fix: add an instance declaration for (Eq Color)
+ In the expression: col == Green
+ In the definition of `it': it = col == Green
How do we add an instance declaration for Show Color
and Eq Color
?
Eq
and Show
for that type:instance Show Color where
-show Red = "Red"
- show Green = "Green"
-
- instance Eq Color where
-???
instance Show Color where
+show Red = "Red"
+ show Green = "Green"
+
+ instance Eq Color where
+???
@@ -731,15 +789,15 @@
Create an instance of Eq
for Color
:
data Color = Red | Green
-
- instance Eq Color where
-???
-
--- Reminder:
-class Eq a where
- (==) :: a -> a -> Bool
- (/=) :: a -> a -> Bool
data Color = Red | Green
+
+ instance Eq Color where
+???
+
+-- Reminder:
+class Eq a where
+ (==) :: a -> a -> Bool
+ (/=) :: a -> a -> Bool
@@ -750,23 +808,23 @@
Which of the following Eq
instances for Color
are valid?
-- (A)
-instance Eq Color where
-==) Red Red = True
- (==) Green Green = True
- (==) _ _ = False
- (
--- (B)
-instance Eq Color where
-/=) Red Red = False
- (/=) Green Green = False
- (/=) _ _ = True
- (
--- (C) Neither of the above
-
--- (D) Either of the above
-- (A)
+instance Eq Color where
+==) Red Red = True
+ (==) Green Green = True
+ (==) _ _ = False
+ (
+-- (B)
+instance Eq Color where
+/=) Red Red = False
+ (/=) Green Green = False
+ (/=) _ _ = True
+ (
+-- (C) Neither of the above
+
+-- (D) Either of the above
@@ -780,12 +838,12 @@
The Eq
class is actually defined like this:
class Eq a where
- (==) :: a -> a -> Bool
-==) x y = not (x /= y) -- Default implementation!
- (
- (/=) :: a -> a -> Bool
-/=) x y = not (x == y) -- Default implementation! (
class Eq a where
+ (==) :: a -> a -> Bool
+==) x y = not (x /= y) -- Default implementation!
+ (
+ (/=) :: a -> a -> Bool
+/=) x y = not (x == y) -- Default implementation! (
The class provides default implementations for its methods
@@ -793,11 +851,11 @@An instance can define any of the two methods and get the other one for free
Use :info
to find out which methods you have to define:
> :info Eq
- λclass Eq a where
- (==) :: a -> a -> Bool
- (/=) :: a -> a -> Bool
-{-# MINIMAL (==) | (/=) #-} -- HERE HERE!!!
> :info Eq
+ λclass Eq a where
+ (==) :: a -> a -> Bool
+ (/=) :: a -> a -> Bool
+{-# MINIMAL (==) | (/=) #-} -- HERE HERE!!!
@@ -805,12 +863,12 @@
If you define:
-instance Eq Color where
--- Nothing here!
instance Eq Color where
+-- Nothing here!
what will the following evaluate to?
-> Red == Green λ
> Red == Green λ
(A) Type error
(B) Runs forever / stack overflow
(C) Other runtime error
@@ -831,16 +889,16 @@This is silly: we should be able to compare and view Color
s “automatically”!
Haskell lets us automatically derive functions for some classes in the standard library.
To do so, we simply dress up the data type definition with
-data Color = Red | Green
-deriving (Eq, Show) -- please generate instances automatically!
data Color = Red | Green
+deriving (Eq, Show) -- please generate instances automatically!
Now we have
-> let col = Red
- λ
-> col
- λRed
-
-> col == Red
- λTrue
> let col = Red
+ λ
+> col
+ λRed
+
+> col == Red
+ λTrue
@@ -856,7 +914,7 @@
@@ -874,10 +932,10 @@
Let’s build a small library for dictionaries mapping keys k
to values v
data Dict k v
-= Empty -- empty dictionary
- | Bind k v (Dict k v) -- bind key `k` to the value `v`
- deriving (Show)
data Dict k v
+= Empty -- empty dictionary
+ | Bind k v (Dict k v) -- bind key `k` to the value `v`
+ deriving (Show)
@@ -887,27 +945,27 @@
We want to be able to do the following with Dict
:
>>> let dict0 = add "cat" 10.0 (add "dog" 20.0 empty)
-
->>> get "cat" dict0
-10
-
->>> get "dog" dict0
-20
-
->>> get "horse" dict0
-error: key not found
>>> let dict0 = add "cat" 10.0 (add "dog" 20.0 empty)
+
+>>> get "cat" dict0
+10
+
+>>> get "dog" dict0
+20
+
+>>> get "horse" dict0
+error: key not found
Okay, lets implement!
--- | 'add key val dict' returns a new dictionary
--- | that additionally maps `key` to `val`
-add :: k -> v -> Dict k v -> Dict k v
-= ???
- add key val dict
--- | 'get key dict' returns the value of `key`
-get :: k -> Dict k v -> v
-= ??? get key dict
-- | 'add key val dict' returns a new dictionary
+-- | that additionally maps `key` to `val`
+add :: k -> v -> Dict k v -> Dict k v
+= ???
+ add key val dict
+-- | 'get key dict' returns the value of `key`
+get :: k -> Dict k v -> v
+= ??? get key dict
@@ -931,8 +989,8 @@
Lets delete the types of add
and get
and see what Haskell says their types are!
> :type get
- λget :: (Eq k) => k -> v -> Dict k v -> Dict k v
> :type get
+ λget :: (Eq k) => k -> v -> Dict k v -> Dict k v
Haskell tells us that we can use any k
type as a key
as long as this type is an instance of the Eq
typeclass.
How, did GHC figure this out?
@@ -963,76 +1021,12 @@Consider the standard typeclass Read
:
-- Not the actual definition, but almost:
-class Read a where
- read :: String -> a
Read
is the opposite of Show
It requires that every instance T
can parse a string and turn it into T
Just like with Show
, most standard type are instances of Read
:
Int
, Integer
, Double
, Char
, Bool
, etc
-
-
-
-
-
-
-
-
What does the expression read "2"
evaluate to?
(A) Type error
-(B) "2"
(C) 2
(D) 2.0
(E) Run-time error
-
-
-
-
-
-
Haskell is foxed!
-read
functions to run!Did we want an Int
or a Double
or maybe something else altogether?
-
Thus, here an explicit type annotation is needed to tell Haskell -what to convert the string to:
-> (read "2") :: Int
- λ2
-
-> (read "2") :: Float
- λ2.0
-
-> (read "2") :: String
- λ???
Note the different results due to the different types.
-
-
-
-
-
-
-
-
-
-
diff --git a/lectures/07-classes.md b/lectures/07-classes.md
index b659ec5..900a1d5 100644
--- a/lectures/07-classes.md
+++ b/lectures/07-classes.md
@@ -36,7 +36,7 @@ Will help us add cool features to the Nano interpreter!
1. **Why type classes?**
2. Standard type classes
3. Creating new instances
-4. Using type classes
+4. Typeclasses and Polymorphism
5. Creating new type classes
@@ -361,7 +361,7 @@ What would be a reasonable type for the equality operator?
1. Why type classes? [done]
2. **Standard type classes**
3. Creating new instances
-4. Using type classes
+4. Typeclasses and Polymorphism
5. Creating new type classes
@@ -425,6 +425,46 @@ instance Eq Double
...
```
+
+
+
+
+
+
+
+
+## The `Ord` Typeclass
+
+The type class `Ord` is for totally ordered values:
+
+```haskell
+class Eq a => Ord a where
+ (<) :: a -> a -> Bool
+ (<=) :: a -> a -> Bool
+ (>) :: a -> a -> Bool
+ (>=) :: a -> a -> Bool
+```
+
+For example:
+
+```haskell
+λ> 2 < 3
+True
+
+λ> "cat" < "dog"
+True
+```
+
+
+
+
+Note `Eq a =>` in the class definition!
+
+A type `T` _is an instance of_ `Ord` if
+
+1. `T` is *also* an instance of `Eq`, and
+2. It defines functions for comparing values for inequality
+
@@ -454,6 +494,7 @@ class Num a where
+
## The `Show` Type Class
The type class `Show` requires that instances be convertible to `String`
@@ -482,44 +523,83 @@ Indeed, we can test this on different (built-in) types
+
+
+
+
-## The `Ord` Typeclass
-
-The type class `Ord` is for totally ordered values:
+## The `Read` Typeclass
```haskell
-class Eq a => Ord a where
- (<) :: a -> a -> Bool
- (<=) :: a -> a -> Bool
- (>) :: a -> a -> Bool
- (>=) :: a -> a -> Bool
+-- Not the actual definition, but almost:
+class Read a where
+ read :: String -> a
```
-For example:
+`Read` is the _opposite_ of `Show`
+
+ - It requires that every instance `T` can parse a string and turn it into `T`
+
+ - Just like with `Show`, most standard type are instances of `Read`:
+
+ - `Int`, `Integer`, `Double`, `Char`, `Bool`, etc
-```haskell
-λ> 2 < 3
-True
+
+
+
+
+
+
+
+
+
-λ> "cat" < "dog"
-True
-```
+## QUIZ
+
+What does the expression `read "2"` evaluate to?
+**(A)** Type error
+
+**(B)** `"2"`
+
+**(C)** `2`
+
+**(D)** `2.0`
+
+**(E)** Run-time error
+
+
+
+
+
-Note `Eq a =>` in the class definition!
+Haskell is foxed!
-A type `T` _is an instance of_ `Ord` if
+- Doesn't know _what type_ to convert the string to!
+- Doesn't know _which_ of the `read` functions to run!
-1. `T` is *also* an instance of `Eq`, and
-2. It defines functions for comparing values for inequality
+Did we want an `Int` or a `Double` or maybe something else altogether?
+
+
+
+
+Thus, here an **explicit type annotation** is needed to tell Haskell
+what to convert the string to:
+
+```haskell
+λ> (read "2") :: Int
+2
+
+λ> (read "2") :: Float
+2.0
-
+λ> (read "2") :: String
+???
+```
+
+Note the different results due to the different types.
@@ -528,6 +608,8 @@ A type `T` _is an instance of_ `Ord` if
+
+
## Standard Typeclass Hierarchy
Haskell comes equipped with a rich set of built-in classes.
@@ -553,7 +635,7 @@ because for something to be an `Ord` it must also be an `Eq`.
1. Why type classes? [done]
2. Standard type classes [done]
3. **Creating new instances**
-4. Using type classes
+4. Typeclasses and Polymorphism
5. Creating new type classes
@@ -859,7 +941,7 @@ True
1. Why type classes? [done]
2. Standard type classes [done]
3. Creating new instances [done]
-4. **Using type classes**
+4. **Typeclasses and Polymorphism**
5. Creating new type classes
@@ -987,91 +1069,7 @@ Write an optimized version of
_(How) do you need to change the types of `get` and `add`?_
-
-
-
-
-
-
-
-
-
-
-
-## Explicit Type Annotations
-
-Consider the standard typeclass `Read`:
-
-```haskell
--- Not the actual definition, but almost:
-class Read a where
- read :: String -> a
-```
-
-`Read` is the _opposite_ of `Show`
-
- - It requires that every instance `T` can parse a string and turn it into `T`
-
- - Just like with `Show`, most standard type are instances of `Read`:
-
- - `Int`, `Integer`, `Double`, `Char`, `Bool`, etc
-
-
-
-
-
-
-
-
-
-
-## QUIZ
-
-What does the expression `read "2"` evaluate to?
-
-**(A)** Type error
-
-**(B)** `"2"`
-
-**(C)** `2`
-
-**(D)** `2.0`
-
-**(E)** Run-time error
-
-
-
-
-
-
-
-
-Haskell is foxed!
-
-- Doesn't know _what type_ to convert the string to!
-- Doesn't know _which_ of the `read` functions to run!
-
-Did we want an `Int` or a `Double` or maybe something else altogether?
-
-
-
-
-Thus, here an **explicit type annotation** is needed to tell Haskell
-what to convert the string to:
-
-```haskell
-λ> (read "2") :: Int
-2
-
-λ> (read "2") :: Float
-2.0
-
-λ> (read "2") :: String
-???
-```
-
-Note the different results due to the different types.
@@ -1089,7 +1087,7 @@ Note the different results due to the different types.
1. Why type classes? [done]
2. Standard type classes [done]
3. Creating new instances [done]
-4. Using type classes [done]
+4. Typeclasses and Polymorphism [done]
5. **Creating new type classes**