16 Nov
Simple types
Work like an alias for an existing type
type Temperature = Float
Declaring objects of the new type
summer :: Temperature
summer = 30
Defining functions using the new type
isCold :: Temperature -> Bool
isCold temp = (temp < 10)
> isCold summer
False
The defined function works for Temperature
objects as well as the aliased type, plain Float
winter :: Float
winter = 4.5
> isCold winter
True
Algebraic data types
Similar to enum
in other languages
data State = Liquid | Solid | Gas -- matter can be in one of the 3 states
Declaring objects
deskState :: State
deskState = Solid
Comparing
eqState :: State -> State -> Bool
eqState Liquid Liquid = True
eqState Solid Solid = True
eqState Gas Gas = True
eqState _ _ = False -- any other combination is not equal
Representing/printing, similar to the toString()
method in other languages
showState :: State -> String
showState Liquid = "Liquid"
showState Solid = "Solid"
showState Gas = "Gas"
Data types with arguments
type Width = Float
type Height = Float
type Radius = Float
data Shape = Circle Radius -- a shape is either a circle (which has radius)
| Rect Width Height -- or a rectangle (which has width and height)
Declaring objects
deskShape :: Shape
deskShape = Rect 10 20.5 -- a rectangular desk
Defining functions, using pattern matching
area :: Shape -> Float
area (Circle r) = pi * r^2
area (Rect w h) = w * h
> area deskShape
205.0 -- 10 * 20.5
Overload the show
function for a Shape
instance Show Shape where
show (Circle r) = "Circle " ++ show r
show (Rect w h) = "Rectangle " ++ show w ++ " x " ++ show h
> deskShape
"Rectangle 10.0 x 20.5"
Overload the ==
operator for two Shapes
instance Eq Shape where
(Circle r1) == (Circle r2) = (r1 == r2) -- equal only if they have the same radius
(Rect w1 h1) == (Rect w2 h2) = (w1 == w2) && (h1 == h2) -- if their dimensions match
shape1 == shape2 = False -- anything else is not equal
> deskShape == (Rect 5 5)
False
Projections
type Name = String
type Age = Int
data Person = Person Name Age
john :: Person
john = Person "John" 25
Extract a certain field from an object, similar to person.getAge()
in other languages
ageOf :: Person -> Age
ageOf (Person name age) = age
> ageOf john
25
Using it
isOverage :: Person -> Bool
isOverage pers = (ageOf pers > 18)
> isOverage john
True
Entries
Similar to class
definitions in other languages
data Superhero = Superhero { name :: Name
, power :: String
} deriving (Show, Eq) -- default implementation
Declaring objects can be done in either way
superman, batman :: Superhero
superman = Superhero "Superman" "flying"
batman = Superhero { name = "Batman", power = "rich" } -- alternative declaration
Using deriving (Show, Eq)
gives the default implementation for show
and ==
> superman
Superhero {name = "Superman", power = "flying"} -- default representation
> superman == batman -- element-wise comparison
False
Projections are implicit
hiddenIdentity :: Superhero -> Name
hiddenIdentity hero = reverse (name hero) -- like hero.name in other languages
> hiddenIdentity batman
"namtaB"
Updating fields
depower :: Superhero -> Superhero
depower hero = hero { power = "none"} -- update the `power` field
> depower superman
Superhero {name = "Superman", power = "none"}