Haskell 7

advertisement
Haskell
Chapter 7
Topics







Defining data types
Exporting types
Type parameters
Derived instances
Type synonyms
Either
Type classes

Not covered






record syntax
recursive data structures
subclassing
parameterized types as
instances of type classes
Yes-No type class (emulate
JavaScript-like behavior)
Functor type class
Define a new data type
data Bool = False | True
 data keyword indicates a new data type (Bool is not new,
just an example)
 False and True are value constructors
 | is “or” – Bool can be False or True
 Type name and value constructors must start with capital
letter
 Value constructors are actually functions that return a
value of a data type
Shape example
-- Circle parms coordinates and radius
-- Rectangle parms upper left and lower right coordinates
data Shape = Circle Float Float Float
| Rectangle Float Float Float Float




*Main> :t Circle
Circle :: Float -> Float -> Float -> Shape
*Main> :t Rectangle
Rectangle :: Float -> Float -> Float -> Float -> Shape
Shape continued
area :: Shape -> Float
area (Circle _ _ r) = pi * r ^2
area (Rectangle x1 y1 x2 y2) = (abs $ x2 - x1) * (abs y2 - y1)

Notice the pattern match against constructor

*Main> let c = Circle 3 4 5
*Main> area c
78.53982









But we don’t know how to show a circle (yet)
*Main> c
<interactive>:15:1:
No instance for (Show Shape)
arising from a use of `print'
Possible fix: add an instance declaration for (Show Shape)
In a stmt of an interactive GHCi command: print it
remember $ is function application
Updating shape to be displayed
data Shape = Circle Float Float Float | Rectangle Float Float
Float Float
deriving (Show)



*Main> let c = Circle 3 4 5
*Main> c
Circle 3.0 4.0 5.0
Improving Shape with a Point data type
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float | Rectangle Point Point deriving (Show)
area :: Shape -> Float
area (Circle _ r) = pi * r ^2
area (Rectangle (Point x1 y1) (Point x2 y2)) = (abs $ x2 - x1) * (abs y2 - y1)


*Main> area (Rectangle (Point 0 0) (Point 100 100))
10000.0
Another method for Shapes
nudge :: Shape -> Float -> Float -> Shape
nudge (Circle (Point x y) r) dx dy = Circle (Point (x+dx) (y+dy)) r
nudge (Rectangle (Point x1 y1) (Point x2 y2)) dx dy =
Rectangle (Point (x1+dx) (y1+dy)) (Point (x2+dx) (y2+dy))


*Main> nudge (Circle (Point 34 34) 10) 5 10
Circle (Point 39.0 44.0) 10.0
Exporting shape
module Shapes
( Point(..)
, Shape(..)
, area
, nudge
) where
 Shape(..) exports all value constructors (in this case
Circle and Rectangle).
 Makes it easy to add more shapes later (OCP)
 If just export Shape, not Shape(..), can’t pattern match
(Programming Languages: support for encapsulation)
Type Constructors



A value constructor takes some parameters, produces a
new value (e.g., Circle takes 3 values, returns a circle
value)
A type constructor takes a type as a parameter, returns a
new type
Maybe type constructor defined as:
data Maybe a = Nothing | Just a

Can’t have just Maybe… needs to be Maybe something
Type Constructors and Strong Typing


Why is this useful? Strong typing.
In Java, null can match any Object type.
public Point fn() { return null; }
public Rectangle fn() { return null; }
public Object fn() { return null; }

In Haskell, must be more specific. If might be “null” then:
playerAt :: a -> Position -> Maybe Player

If definitely a Player returned then:
playerAt :: a -> Position -> Player
More on typing: https://en.wikipedia.org/wiki/Strong_and_weak_typing
Usage


Due to type inference, often don’t pass parameters to
type constructors explicitly
If a value is Just ‘a’, Haskell infers type as Maybe Char

Concrete type either doesn’t take any type parameters,
e.g., Int, Bool OR has filled type parameters (Maybe Char)

List type takes a parameter, returns concrete type
[Int] is an example

Play with it












*Main> Just "Haha"
Just "Haha"
*Main> Just 84
Just 84
*Main> :t Just "Haha"
Just "Haha" :: Maybe [Char]
*Main> :t Just 84
Just 84 :: Num a => Maybe a
*Main> :t Nothing
Nothing :: Maybe a
*Main> Just 10 :: Maybe Double
Just 10.0
Type class \= Java class
In Java, we use a class as a blueprint to create objects
 In Haskell, you use type classes to make a data type, then
think about how it can act
 We do this with deriving
 If types of all fields are part of a type class, then our new
type can be part of a type class
data Person = Person { name :: String, age :: Int }

deriving (Eq, Show)
Example









*Shapes> let frodo = Person {name = "Frodo Baggins", age = 43}
*Shapes> let bilbo = Person {name = "Bilbo Baggins", age = 100}
*Shapes> bilbo
Person {name = "Bilbo Baggins", age = 100}
*Shapes> bilbo == frodo
False
*Shapes> let imposter = Person {name = "Frodo Baggins", age =
43}
*Shapes> frodo == imposter
True
Enum example
data Day = Monday | Tuesday | Wednesday | Thursday | Friday |
Saturday | Sunday
deriving (Eq, Show, Ord, Read, Bounded, Enum)
*Chap7> Wednesday
*Chap7> minBound :: Day
Wednesday
Monday
*Chap7> show Wednesday
*Chap7> maxBound :: Day
"Wednesday"
Sunday
*Chap7> read "Saturday" :: Day
*Chap7> let weekend = [Friday .. Sunday]
Saturday
(note space before ..)
*Chap7> Saturday == Sunday
*Chap7> weekend
False
[Friday,Saturday,Sunday]
*Chap7> Monday `compare` Wednesday
LT
*Chap7> Saturday > Friday
True
Type Synonyms

[Char] and String are type synonyms
type PhoneNumber = String
type Name = String
type PhoneBook = [(Name, PhoneNumber)]
inPhoneBook :: Name -> PhoneNumber ->
PhoneBook -> Bool
inPhoneBook name pnumber pbook =
(name, pnumber) `elem` pbook
Not covered: parameterized type synonyms
Could be Either


Use to encapsulate a value of one type or another
Is defined as:
data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show)
*Chap7> Right 20









Right 20
*Chap7> Left "Whoa"
Left "Whoa"
*Chap7> :t Right 'a'
Right 'a' :: Either a Char
*Chap7> :t Left True
Left True :: Either Bool b
Either with try




The try functions
try :: Exception e => IO a -> IO (Either e a)Source
Similar to catch, but returns an Either result which
is (Right a) if no exception of type e was raised,
or (Left ex) if an exception of type e was raised and its
value is ex. If any other type of exception is raised than it
will be propogated up to the next enclosing exception
handler.
try a = catch (Right `liftM` a) (return . Left)
http://www.haskell.org/ghc/docs/6.12.2/html/libraries/base-4.2.0.1/Control-Exception.html#7
Usage

Maybe can be used if function might return a result or fail
Either can be used if there are multiple possible results

You’ll explore this more in the homework

Type Classes 102


Type classes are sort of like interfaces: they define
behavior
Types that can behave that way are made instances (just
means they can use the functions associated with that
type class)
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
x == y = not (x /= y)
x /= y = not (x == y)
note the mutual recursion… only need to
implement one!
Using a type class
data TrafficLight = Red | Yellow | Green
instance Eq TrafficLight where
Red == Red = True
Green == Green = True
Yellow == Yellow = True
_ == _ = False
instance Show TrafficLight where
show Red = "Red Light"
show Green = "Green Light"
show Yellow = "Yellow Light"
Using the Traffic Light










*Chap7> Red
Red Light
*Chap7> Red
Red Light
*Chap7> Red == Red
True
*Chap7> Red == Green
False
*Chap7> Red `elem` [Red, Green,Yellow]
True
Related documents
Download