Lecture 2.0 — 2016-09-01

Introduction, continued

This lecture is written in literate Haskell; you can download the raw source.

import Prelude hiding ((.))

We picked up where we left off, writing a few simple functions on our simple datatype for days of the week.

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

We added this deriving clause so we’d be able to use (in)equality on Days and print them out. We wrote several versions of the same function.

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

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

The above two forms are completely equivalent. The next form required us to add deriving Eq to the datatype definition. (The parens are only necessary when you derive more than thing.)

isWeekday'' :: Day -> Bool
isWeekday'' d = d /= Saturday && d /= Sunday

Finally, we played around with function composition, written f . g. It lets us program in point-free style, where we avoid naming variables.

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

isWeekend' :: Day -> Bool
isWeekend' = not . isWeekday

Note that this definition is the same as:

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

But there’s no point in writing the d out. It’s a general rule that we can take f x = e x and turn it into f = e when e doesn’t mention x.

It took us a while to figure it out, but we ultimately wrote down our own definition of (.). (Note that use of parens to mention an operator without using. The use-mention distinction is a critical one; in English writing, we tend to use quotes to distinguish, say, me (Michael Greenberg) from “me”, the first-person singular pronoun.)

(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)

Finally, we talked about lists. Haskell defines lists like so:

{-
data ([]) a =
    []
  | (:) a [a]
-}

and we can write lists like (here we declare a number of variables—l1 through l4—as all having the same type, [Day]):

l1, l2, l3, l4 :: [Day]
l1 = []
l2 = Monday:[]
l3 = Tuesday:Thursday:[]
l4 = [Tuesday,Thursday]

Finally, we wrote our first function on list, which finds all of the weekdays in a list:

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