# Lecture 4: Secret Code, User-defined datatypes

```
{-# OPTIONS -Wall -fno-warn-type-defaults #-}
module Lec4 where
```

```
import Prelude hiding (Maybe,Just,Nothing,Either,Left,Right)
import Test.HUnit
```

REMINDER: HW #1 is due tomorrow at 8PM! HW #2 will be available on Wednesday.

# Back to Secret Code

Recall the plan that Chris was working through with you last Wednesday:

We will develop a Haskell program to encode files from disk.

We will modify the program so that it can both encode and decode files.

According to Chris, you worked through the first part of the SecretCode, but did not finish it. We'll pick up there.

# User-defined datatypes

So far, we've mostly talked about how to use the types that appear in the Haskell standard library. We also discussed a few type synonyms, like

` type XY = (Double,Double)`

from the last lecture, but we haven't described any ways to define really *new* types.

As a motivating example, suppose you are writing an application that deals with calendars and you need to represent the days of the week. You might be tempted to use `String`

s or `Int`

s, but both of these choices have issues. If you use

type Day = String

there will be lots of `Day`

s that don't actually represent real days. Also, you will need to devise and adhere to some sort of standardization - is Monday represented by "Monday", "monday", "MONDAY", or "Mon"? Should you handle more than one?

The choice

type Day = Int

has similar problems. There are lots of Ints that won't represent valid days. Also you'll have to remember whether you pick Sunday or Monday to be the first day of the week, and whether it is represented by 0 or 1.

Haskell has a better solution: user-defined datatypes:

```
data Day = Monday
| Tuesday
| Wednesday
| Thursday
| Friday
| Saturday
| Sunday
deriving (Show, Eq)
```

The new values (`Monday`

, `Tuesday`

, etc.) are called "constructors". This is a very simple example of a datatype (basically just an enumeration), but we'll see more examples in a minute.

We can define functions on datatypes by pattern matching! For example:

```
nextWeekday :: Day -> Day
nextWeekday Monday = Tuesday
nextWeekday Tuesday = Wednesday
nextWeekday Wednesday = Thursday
nextWeekday Thursday = Friday
nextWeekday Friday = Monday
nextWeekday Saturday = Monday
nextWeekday Sunday = error "BUG: shouldn't"
```

This is great. Now we don't have to worry about the difference between "Monday" and "monday" or which Int corresponds to which day. If we make a typo (for example, write Frday instead of Friday), the compiler will warn us *at compile time*. And if we forget to handle one of the days in some function, the compiler will warn us about that too (inexhaustive pattern match warning).

Let's write one more function on `Day`

s - we can now easily compute when a package will arrive by "two day" shipping:

```
twoBusinessDays :: Day -> Day
twoBusinessDays = nextWeekday . nextWeekday
```

Datatypes can hold data, too. For example, here is a datatype for representing shapes:

```
data Shape =
Circle Float Float Float
| Rectangle Float Float Float Float
```

Here, `Circle`

and `Rectangle`

are the constructors - every `Shape`

must be one or the other. Each constructors has some arguments:

A

`Circle`

is specified by three`Floats`

. These represent the x and y coordinates of the center and the radius.A

`Rectangle`

is specifed by four`Floats`

. The first two are the coordinates of the lower left corner, and the second two are the coordinates of the upper right corner.

We can pattern match on shapes. For example, here is a function that computes the area of any `Shape`

:

```
area :: Shape -> Float
area (Circle _ _ r) = pi * (r * r)
area (Rectangle x1 y1 x2 y2) = (y2 - y1) * (x2 - x1)
```

Note that constructors are first-class Haskell values just all the other values we have seen. Like any value, they have types.

For example the types of `Monday`

and `Tuesday`

shouldn't surprise you:

```
Monday :: Day
Tuesday :: Day
```

The constructors that take arguments have *function* types. For example, you must apply `Circle`

to three `Float`

s to get a `Shape`

:

```
Circle :: Float -> Float -> Float -> Shape
Rectangle :: Float -> Float -> Float -> Float -> Shape
```

# Recursive Types

Datatypes can be defined recursively. That is, their constructors can take other elements of the same type as arguments.

For example, here is one way to define the type of natural numbers:

```
data Nat = Zero
| Succ Nat
```

Every natural number is either Zero, or the successor of some other natural number. For example, we represent 2 as:

```
natTwo :: Nat
natTwo = Succ (Succ Zero)
```

We could write a function convert `Nat`

s to `Int`

s. Of course, we'll do it with pattern matching and recursion:

```
natToInt :: Nat -> Int
natToInt Zero = 0
natToInt (Succ x) = 1 + natToInt x
```

We could also define a function to add two natural numbers:

```
natPlus :: Nat -> Nat -> Nat
-- natPlus Zero Zero = Zero
-- natPlus m Zero = m
natPlus Zero m = m
natPlus (Succ x) y = -- natPlus x (Succ y)
Succ (natPlus x y)
```

Do they work?

```
natToIntTests :: Test
natToIntTests = TestList [ natToInt Zero ~?= 0,
natToInt (Succ (Succ (Succ Zero))) ~?= 3 ]
```

```
natPlusTests :: Test
natPlusTests =
TestList [ natToInt (natPlus (Succ (Succ Zero)) Zero) ~?= 2,
natToInt (natPlus (Succ Zero) (Succ (Succ Zero))) ~?= 3]
```

As another example, we could define a type representing lists of integers:

```
data IntList = INil
| ICons Int IntList
```

So that the list 1,2,3 is represented as:

```
oneTwoThree :: IntList
oneTwoThree = ICons 1 (ICons 2 (ICons 3 INil))
```

For comparison with Haskell's built-in lists, it might help to think of this as:

```
oneTwoThree' :: IntList
oneTwoThree' = 1 `ICons` (2 `ICons` (3 `ICons` INil))
```

We can define functions by recursion on these too, of course:

```
sumOfIntList :: IntList -> Int
sumOfIntList = undefined
```

```
main :: IO ()
main = putStrLn "This is Lec4"
```

[1] Part of this lecture is taken from "Learn You a Haskell for Great Good". http://learnyouahaskell.com/

## News :

Welcome to CIS 552!

See the home page for basic
information about the course, the schedule for the lecture notes
and assignments, the resources for links to the required software
and online references, and the syllabus for detailed information about
the course policies.