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"}
``````