Lecture 1 — 2015-09-02

``module Lec01 where``

We went over the syllabus and we all filled out some notecards, with the following information:

• Name
• Have you taken 81?
• Favorite programming language
• Least favorite programming language
• Spoken languages
• Favorite music right now
• X or Y (name a dialectic and pick a side)
• Other interests

As a result, I’ll have to google for what “trap” music is.

After some tooling around in GHCi, the interpreter, we started writing some real code. An easy arithmetic function…

``````mean :: Int -> Int -> Int
mean x y = (x + y) `div` 2``````

…followed by some more interesting recursive functions:

``````fact :: Int -> Int
fact 0 = 1
fact n = n * (fact (n - 1))

fib :: Int -> Int
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)``````

Then we defined our datatype, discovering along the way that Haskell doesn’t automatically give us things we can `show` or compare for equality (via `==`. The `deriving` clause lets us get these things.

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

We defined isWeekday two different ways. First we had:

``````isWeekday' :: Day -> Bool
isWeekday' Saturday = False
isWeekday' Sunday = False
isWeekday' _ = True``````

and then we saw what happens when you drop off pattern match (an error!). We also looked at the `case` statement:

``````isWeekday :: Day -> Bool
isWeekday d =
case d of
Saturday -> False
Sunday -> False
_ -> True``````

And then we defined functions using other functions. A breeze.

``````isWeekend :: Day -> Bool
isWeekend d = not (isWeekday d)``````

This one was boring.

``````nextDay :: Day -> Day
nextDay Monday = Tuesday
nextDay Tuesday = Wednesday
nextDay Wednesday = Thursday
nextDay Thursday = Friday
nextDay Friday = Saturday
nextDay Saturday = Sunday
nextDay Sunday = Monday``````

But this was more interesting! We get to use a math-like syntax instead of conditionals.

``````weekdays :: [Day] -> [Day]
weekdays []     = []
weekdays (d:ds)
| isWeekday d = d:weekdays ds
| otherwise   = weekdays ds``````

We talked a bit more about lists, defining our own version of the library function `last`.

``````last' :: [a] -> a
last' []     = error "don't do that"
last' [x]    = x
last' (x:xs) = last' xs``````

To tie everything together, we worked on some functions for thinking about points and lines on the Cartesian plane.

``````data Point = Point { xCoord :: Float,
yCoord :: Float }
deriving Show

data Line =
Vert Float
| Sloped { lineSlope :: Float,
lineIntercept :: Float }
deriving Show``````

We went through a couple versions of a function that takes two points and returns a line going them. First, we had:

``````mkLine' :: Point -> Point -> Line
mkLine' p1 p2 =
if xCoord p1 == xCoord p2
then Vert \$ xCoord p1
else
let m = (yCoord p1 - yCoord p2) /
(xCoord p1 - xCoord p2) in
let b = yCoord p1 - (m * xCoord p1) in
Sloped m b``````

But then Eric pointed out that this had a funny behavior when `p1` and `p2` are equal. First we established that you can’t write something like:

``````mkLine p1 p1 = {- error case where the points are the same -}
mkLine p1 p2 = {- normal function -}``````

Rather than having the function call `error`, we decided to use the `Maybe` datatype. By now we had already used the `:i [type name]` and `:t [expression]` commands in GHCi to look at types. Running `:i Maybe`, we got:

``````data Maybe a = Nothing | Just a 	-- Defined in ‘GHC.Base’
-- ... and a bunch of instances we don't really care about right now``````

We then simply changed the type on `mkLine` to return `Maybe Line`, and then the type checker guided us to all the spots we needed to fix.

``````mkLine :: Point -> Point -> Maybe Line
mkLine p1 p2 =
if xCoord p1 == xCoord p2
then if yCoord p1 == yCoord p2
then Nothing
else Just \$ Vert \$ xCoord p1
else
let m = (yCoord p1 - yCoord p2) /
(xCoord p1 - xCoord p2) in
let b = yCoord p1 - (m * xCoord p1) in
Just \$ Sloped m b``````