haskell chapter 7. topics defining data types exporting types type parameters derived instances ...

22
Haskell Chapter 7

Upload: mathew-rusher

Post on 14-Dec-2015

240 views

Category:

Documents


1 download

TRANSCRIPT

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

coordinatesdata 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 continuedarea :: Shape -> Floatarea (Circle _ _ r) = pi * r ^2area (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 itremember $ is function application

Updating shape to be displayeddata 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 typedata 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 Shapesnudge :: 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 shapemodule 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 Parameters A value constructors 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 Why is this useful? Strong typing. In Java, a function might

return a Point or null. This is not possible in Haskell. So if a function may or may not produce a value, then the return type is Maybe something (e.g., Maybe Point)

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 classdata 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 exampledata Day = Monday | Tuesday | Wednesday | Thursday | Friday |

Saturday | Sundayderiving (Eq, Show, Ord, Read, Bounded, Enum)

*Chap7> WednesdayWednesday*Chap7> show Wednesday"Wednesday"*Chap7> read "Saturday" :: DaySaturday*Chap7> Saturday == SundayFalse*Chap7> Monday `compare` WednesdayLT*Chap7> Saturday > FridayTrue

*Chap7> minBound :: DayMonday*Chap7> maxBound :: DaySunday*Chap7> let weekend = [Friday .. Sunday]*Chap7> weekend[Friday,Saturday,Sunday]

Type Synonyms [Char] and String are type synonyms

type PhoneNumber = Stringtype Name = Stringtype 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 -> Boolx == y = not (x /= y) x /= y = not (x == y)

note the mutual recursion… only need to implement one!

Using a type classdata TrafficLight = Red | Yellow | Greeninstance 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