diff --git a/assignments.md b/assignments.md index 4ad602b..f30a857 100644 --- a/assignments.md +++ b/assignments.md @@ -19,7 +19,7 @@ If you get an error when creating a team, **try a different team name** | [HW2](https://classroom.github.com/a/7RMcGUB-) | Random Art | 5/3 | diff --git a/docs/assignments.html b/docs/assignments.html index b289e5c..c759334 100644 --- a/docs/assignments.html +++ b/docs/assignments.html @@ -270,7 +270,7 @@

Assignments

Practice Exams

diff --git a/docs/lectures/01-lambda.html b/docs/lectures/01-lambda.html index 617430e..942bd76 100644 --- a/docs/lectures/01-lambda.html +++ b/docs/lectures/01-lambda.html @@ -283,12 +283,14 @@

1936: Formalization

Alan Turing +

The Turing Machine



Alonzo Church
+

The Lambda Calculus




@@ -473,6 +475,7 @@

QUIZ

D. A and C

E. all of the above


+

Correct answer: A




@@ -678,6 +681,7 @@

QUIZ

D. first occurrence is bound, second and third are free

E. first two occurrences are bound, third is free


+

Correct answer: C




@@ -693,9 +697,9 @@

EXERCISE: Free Variables

A variable x is free in E if there exists a free occurrence of x in E


We can formally define the set of all free variables in a term like so:

-
FV(x)       = ???
-FV(E1 E2)   = ???
-FV(\x -> E) = ???
+
FV(x)       = {x}
+FV(E1 E2)   = FV(E1) + FV(E2)
+FV(\x -> E) = FV(E) \ {x}




@@ -716,6 +720,7 @@

Closed Expressions



What is the shortest closed expression?

+

Answer: \x -> x




@@ -782,7 +787,7 @@

Examples



(\f -> f (\x -> x)) (give apple)
-=b> ???
+=b> give apple (\x -> x)




@@ -805,6 +810,7 @@

QUIZ

D. \y -> y

E. \x -> y


+

Correct answer: D.




@@ -826,6 +832,7 @@

QUIZ

D. apple

E. \x -> x


+

Correct answer: A.




@@ -894,6 +901,9 @@

Capture-Avoiding Substitution

(\y -> E)[x := E'] | not (y in FV(E')) = \y -> E[x := E'] | otherise = undefined -- wait, but what do we do then??? +

Answer: We leave E above alone even though it might contain x, +because in \x -> E every occurrence of x is bound by \x +(hence, there are no free occurrences of x)




@@ -944,10 +954,13 @@

Semantics: αWhat’s wrong with these?

-- (A)
 \f -> f x    =a>   \x -> x x
+

Answer: it violates the side-condition that the new formal (x) must not occur freely in the body

-- (B)
 (\x -> \y -> y) y   =a>   (\x -> \z -> z) z
+

Answer: we should only rename within the body of the abstraction; the second y is a free variable, and hence must remain unchanged

-- (C)
 \x -> (\y -> x y)   =a>    \y -> (\y -> y y)
+

Answer: the new formal y does not occur freely in the body, but the substitution is not capture-avoiding




@@ -964,7 +977,8 @@

Semantics: αTricky Example Revisited


(\x -> (\y -> x)) y
-=a> ???
+=a> (\x -> (\z -> x)) y +=b> \z -> y



To avoid getting confused, you can always rename formals, so that different variables have different names!

@@ -1004,6 +1018,7 @@

QUIZ

C. x (\y -> y) z

D. x ((\y -> y) z)

E. B and D

+

Answer: E




@@ -1037,8 +1052,9 @@

Examples of Evaluation

(\x -> x) apple
   =b> apple


-
(\f -> (\x -> x) f) (\x -> x)
-  =?> ???
+
(\f -> f (\x -> x)) (\x -> x)
+  =b> (\x -> x) (\x -> x)
+  =b> \x -> x
-
eval ite_false:
-  ITE FALSE egg ham
-
-  -- fill the steps in!
-
-  =b> ham  
+
eval ite_false:
+  ITE FALSE egg ham
+  =d> (\b x y -> b     x   y) FALSE egg ham   -- expand def ITE  
+  =b>   (\x y -> FALSE x   y)       egg ham   -- beta-step
+  =b>     (\y -> FALSE egg y)           ham   -- beta-step
+  =b>            FALSE egg ham                -- expand def FALSE
+  =d>      (\x y -> y) egg ham                -- beta-step
+  =b>        (\y -> y)     ham                -- beta-step
+  =b> ham




@@ -1281,39 +1303,41 @@

EXERCISE: Boolean Operators

ELSA: https://elsa.goto.ucsd.edu/index.html

Click here to try this exercise

Now that we have ITE it’s easy to define other Boolean operators:

-
let NOT = \b     -> ???
-let OR  = \b1 b2 -> ???
-let AND = \b1 b2 -> ???
+
let NOT = \b     -> ITE b FALSE TRUE 
+
+let AND = \b1 b2 -> ITE b1 b2 FALSE
+
+let OR  = \b1 b2 -> ITE b1 TRUE b2

When you are done, you should get the following behavior:

-
eval ex_not_t:
-  NOT TRUE =*> FALSE
-  
-eval ex_not_f:
-  NOT FALSE =*> TRUE 
-  
-eval ex_or_ff:
-  OR FALSE FALSE =*> FALSE
-
-eval ex_or_ft:
-  OR FALSE TRUE =*> TRUE
-  
-eval ex_or_ft:
-  OR TRUE FALSE =*> TRUE
-
-eval ex_or_tt:
-  OR TRUE TRUE =*> TRUE
-  
-eval ex_and_ff:
-  AND FALSE FALSE =*> FALSE
-
-eval ex_and_ft:
-  AND FALSE TRUE =*> FALSE
-  
-eval ex_and_ft:
-  AND TRUE FALSE =*> FALSE
-
-eval ex_and_tt:
-  AND TRUE TRUE =*> TRUE
+
eval ex_not_t:
+  NOT TRUE =*> FALSE
+  
+eval ex_not_f:
+  NOT FALSE =*> TRUE 
+  
+eval ex_or_ff:
+  OR FALSE FALSE =*> FALSE
+
+eval ex_or_ft:
+  OR FALSE TRUE =*> TRUE
+  
+eval ex_or_ft:
+  OR TRUE FALSE =*> TRUE
+
+eval ex_or_tt:
+  OR TRUE TRUE =*> TRUE
+  
+eval ex_and_ff:
+  AND FALSE FALSE =*> FALSE
+
+eval ex_and_ft:
+  AND FALSE TRUE =*> FALSE
+  
+eval ex_and_ft:
+  AND TRUE FALSE =*> FALSE
+
+eval ex_and_tt:
+  AND TRUE TRUE =*> TRUE




@@ -1369,18 +1393,18 @@

λ-ca

Pairs : API

We need to define three functions

-
let PAIR = \x y -> ???    -- Make a pair with elements x and y 
-                          -- { fst : x, snd : y }
-let FST  = \p -> ???      -- Return first element 
-                          -- p.fst
-let SND  = \p -> ???      -- Return second element
-                          -- p.snd
+
let PAIR = \x y -> ???    -- Make a pair with elements x and y 
+                          -- { fst : x, snd : y }
+let FST  = \p -> ???      -- Return first element 
+                          -- p.fst
+let SND  = \p -> ???      -- Return second element
+                          -- p.snd

such that

-
eval ex_fst: 
-  FST (PAIR apple banana) =~> apple
-
-eval ex_snd:
-  SND (PAIR apple banana) =~> banana
+
eval ex_fst: 
+  FST (PAIR apple banana) =~> apple
+
+eval ex_snd:
+  SND (PAIR apple banana) =~> banana




@@ -1396,9 +1420,9 @@

Pairs : API

Pairs: Implementation

A pair of x and y is just something that lets you pick between x and y! (i.e. a function that takes a boolean and returns either x or y)

-
let PAIR = \x y -> (\b -> ITE b x y)
-let FST  = \p -> p TRUE   -- call w/ TRUE, get first value
-let SND  = \p -> p FALSE  -- call w/ FALSE, get second value
+
let PAIR = \x y -> (\b -> ITE b x y)
+let FST  = \p -> p TRUE   -- call w/ TRUE, get first value
+let SND  = \p -> p FALSE  -- call w/ FALSE, get second value




@@ -1415,22 +1439,26 @@

EXERCISE: Triples

How can we implement a record that contains three values?

ELSA: https://elsa.goto.ucsd.edu/index.html

Click here to try this exercise

-
let TRIPLE = \x y z -> ???
-let FST3   = \t -> ???
-let SND3   = \t -> ???
-let THD3   = \t -> ???
-
-eval ex1:
-  FST3 (TRIPLE apple banana orange)
-  =~> apple
-
-eval ex2:
-  SND3 (TRIPLE apple banana orange)
-  =~> banana 
-
-eval ex3:
-  THD3 (TRIPLE apple banana orange)
-  =~> orange
+
let TRIPLE = \x y z -> ???
+let FST3   = \t -> ???
+let SND3   = \t -> ???
+let THD3   = \t -> ???
+
+eval ex1:
+  FST3 (TRIPLE apple banana orange)
+  =~> apple
+
+eval ex2:
+  SND3 (TRIPLE apple banana orange)
+  =~> banana 
+
+eval ex3:
+  THD3 (TRIPLE apple banana orange)
+  =~> orange
+
let TRIPLE = \x y z -> PAIR x (PAIR y z)
+let FST3  = \t -> FST t
+let SND3  = \t -> FST (SND t)
+let THD3  = \t -> SND (SND t)




@@ -1491,10 +1519,10 @@

Natural Numbers: API

  • Comparisons: IS_ZERO, EQ
  • Such that they respect all regular laws of arithmetic, e.g.

    -
    IS_ZERO ZERO       =~> TRUE
    -IS_ZERO (INC ZERO) =~> FALSE
    -INC ONE            =~> TWO
    -...
    +
    IS_ZERO ZERO       =~> TRUE
    +IS_ZERO (INC ZERO) =~> FALSE
    +INC ONE            =~> TWO
    +...




    @@ -1511,13 +1539,13 @@

    Natural Numbers: Implementation

    Church numerals: a number N is encoded as a combinator that calls a function on an argument N times

    -
    let ONE   = \f x -> f x
    -let TWO   = \f x -> f (f x)
    -let THREE = \f x -> f (f (f x))
    -let FOUR  = \f x -> f (f (f (f x)))
    -let FIVE  = \f x -> f (f (f (f (f x))))
    -let SIX   = \f x -> f (f (f (f (f (f x)))))
    -...
    +
    let ONE   = \f x -> f x
    +let TWO   = \f x -> f (f x)
    +let THREE = \f x -> f (f (f x))
    +let FOUR  = \f x -> f (f (f (f x)))
    +let FIVE  = \f x -> f (f (f (f (f x))))
    +let SIX   = \f x -> f (f (f (f (f (f x)))))
    +...

    QUIZ: Church Numerals

    Which of these is a reasonable encoding of ZERO ?

      @@ -1527,10 +1555,12 @@

      QUIZ: Church Numerals

    • D: let ZERO = \x -> x

    • E: None of the above

    +

    Answer: A




    Does this function look familiar?

    +

    Answer: It’s the same as FALSE!




    @@ -1543,8 +1573,8 @@

    QUIZ: Church Numerals



    λ-calculus: Increment

    -
    -- Call `f` on `x` one more time than `n` does
    -let INC   = \n -> (\f x -> ???)
    +
    -- Call `f` on `x` one more time than `n` does
    +let INC   = \n -> (\f x -> f (n f x))




    @@ -1558,12 +1588,12 @@

    λ-

    Example:

    -
    eval inc_zero :
    -  INC ZERO
    -  =d> (\n f x -> f (n f x)) ZERO
    -  =b> \f x -> f (ZERO f x)
    -  =*> \f x -> f x
    -  =d> ONE
    +
    eval inc_zero :
    +  INC ZERO
    +  =d> (\n f x -> f (n f x)) ZERO
    +  =b> \f x -> f (ZERO f x)
    +  =*> \f x -> f x
    +  =d> ONE




    @@ -1579,30 +1609,30 @@

    λ-

    EXERCISE

    Fill in the implementation of ADD so that you get the following behavior

    Click here to try this exercise

    -
    let ZERO = \f x -> x
    -let ONE  = \f x -> f x
    -let TWO  = \f x -> f (f x)
    -let INC  = \n f x -> f (n f x)
    -
    -let ADD  = fill_this_in 
    -
    -eval add_zero_zero: 
    -  ADD ZERO ZERO =~> ZERO
    -
    -eval add_zero_one: 
    -  ADD ZERO ONE =~> ONE
    -
    -eval add_zero_two: 
    -  ADD ZERO TWO =~> TWO 
    -
    -eval add_one_zero: 
    -  ADD ONE ZERO =~> ONE
    -
    -eval add_one_zero: 
    -  ADD ONE ONE =~> TWO
    -
    -eval add_two_zero: 
    -  ADD TWO ZERO =~> TWO  
    +
    let ZERO = \f x -> x
    +let ONE  = \f x -> f x
    +let TWO  = \f x -> f (f x)
    +let INC  = \n f x -> f (n f x)
    +
    +let ADD  = fill_this_in 
    +
    +eval add_zero_zero: 
    +  ADD ZERO ZERO =~> ZERO
    +
    +eval add_zero_one: 
    +  ADD ZERO ONE =~> ONE
    +
    +eval add_zero_two: 
    +  ADD ZERO TWO =~> TWO 
    +
    +eval add_one_zero: 
    +  ADD ONE ZERO =~> ONE
    +
    +eval add_one_zero: 
    +  ADD ONE ONE =~> TWO
    +
    +eval add_two_zero: 
    +  ADD TWO ZERO =~> TWO  




    @@ -1616,15 +1646,15 @@

    EXERCISE



    λ-calculus: Addition

    -
    --  Call `f` on `x` exactly `n + m` times
    -let ADD = \n m -> n INC m
    +
    --  Call `f` on `x` exactly `n + m` times
    +let ADD = \n m -> n INC m




    Example:

    -
    eval add_one_zero :
    -  ADD ONE ZERO
    -  =~> ONE
    +
    eval add_one_zero :
    +  ADD ONE ZERO
    +  =~> ONE




    @@ -1644,6 +1674,7 @@

    QUIZ

    C. let MULT = \n m -> m (ADD n) ZERO

    D. let MULT = \n m -> n (ADD m ZERO)

    E. let MULT = \n m -> (n ADD m) ZERO

    +

    Answer: B or C




    @@ -1657,15 +1688,15 @@

    QUIZ



    λ-calculus: Multiplication

    -
    --  Call `f` on `x` exactly `n * m` times
    -let MULT = \n m -> n (ADD m) ZERO
    +
    --  Call `f` on `x` exactly `n * m` times
    +let MULT = \n m -> n (ADD m) ZERO




    Example:

    -
    eval two_times_three :
    -  MULT TWO ONE
    -  =~> TWO
    +
    eval two_times_three :
    +  MULT TWO ONE
    +  =~> TWO




    @@ -1701,7 +1732,7 @@

    Programming in λ-calculus: Recursion


    I want to write a function that sums up natural numbers up to n:

    -
    \n -> ...          -- 0 + 1 + 2 + ... + n
    +
    \n -> ...          -- 0 + 1 + 2 + ... + n




    @@ -1714,9 +1745,9 @@

    λ-

    QUIZ

    Is this a correct implementation of SUM?

    -
    let SUM = \n -> ITE (ISZ n) 
    -            ZERO 
    -            (ADD n (SUM (DEC n)))
    +
    let SUM = \n -> ITE (ISZ n) 
    +            ZERO 
    +            (ADD n (SUM (DEC n)))

    A. Yes

    B. No


    @@ -1734,9 +1765,9 @@

    QUIZ

  • Named terms in Elsa are just syntactic sugar
  • To translate an Elsa term to λ-calculus: replace each name with its definition
  • -
    \n -> ITE (ISZ n) 
    -        ZERO 
    -        (ADD n (SUM (DEC n))) -- But SUM is not a thing!
    +
    \n -> ITE (ISZ n) 
    +        ZERO 
    +        (ADD n (SUM (DEC n))) -- But SUM is not a thing!



    Recursion:

    @@ -1774,10 +1805,10 @@

    λ

    Step 1: Pass in the function to call “recursively”

    -
    let STEP = 
    -  \rec -> \n -> ITE (ISZ n) 
    -                  ZERO 
    -                  (ADD n (rec (DEC n))) -- Call some rec
    +
    let STEP = 
    +  \rec -> \n -> ITE (ISZ n) 
    +                  ZERO 
    +                  (ADD n (rec (DEC n))) -- Call some rec




    @@ -1790,12 +1821,12 @@

    λSTEP rec THREE =*> ADD THREE (rec TWO)

    So:

    -
        STEP (STEP (STEP (STEP f))) THREE
    -=*> ADD THREE (STEP (STEP (STEP f)) TWO)
    -=*> ADD THREE (ADD TWO (STEP (STEP f) ONE))
    -=*> ADD THREE (ADD TWO (ADD ONE (STEP f ZERO)))
    -=*> ADD THREE (ADD TWO (ADD ONE ZERO))
    ---  ^ Exactly what we want!
    +
        STEP (STEP (STEP (STEP f))) THREE
    +=*> ADD THREE (STEP (STEP (STEP f)) TWO)
    +=*> ADD THREE (ADD TWO (STEP (STEP f) ONE))
    +=*> ADD THREE (ADD TWO (ADD ONE (STEP f ZERO)))
    +=*> ADD THREE (ADD TWO (ADD ONE ZERO))
    +--  ^ Exactly what we want!




    @@ -1818,8 +1849,8 @@

    λλ-calculus: Fixpoint Combinator

    Wanted: a combinator FIX such that FIX STEP calls STEP with itself as the first argument:

    -
    FIX STEP
    -=*> STEP (FIX STEP)
    +
    FIX STEP
    +=*> STEP (FIX STEP)


    (In math: a fixpoint of a function f(x) is a point x, such that f(x) = x)


    @@ -1827,16 +1858,16 @@

    λ

    Once we have it, we can define:

    -
    let SUM = FIX STEP
    +
    let SUM = FIX STEP

    Then by property of FIX we have:

    -
    SUM =*> STEP SUM -- (1)
    -
    eval sum_three:
    -                             SUM    THREE   -- (1)
    -  =*>                   STEP SUM    THREE   -- (1)
    -  =*>             STEP (STEP SUM)   THREE   -- (1)
    -  =*>       STEP (STEP (STEP SUM))  THREE   -- (1)
    -  =*> STEP (STEP (STEP (STEP SUM))) THREE   -- we've seen this before
    -  =*> ADD THREE (ADD TWO (ADD ONE ZERO))
    +
    SUM =*> STEP SUM -- (1)
    +
    eval sum_three:
    +                             SUM    THREE   -- (1)
    +  =*>                   STEP SUM    THREE   -- (1)
    +  =*>             STEP (STEP SUM)   THREE   -- (1)
    +  =*>       STEP (STEP (STEP SUM))  THREE   -- (1)
    +  =*> STEP (STEP (STEP (STEP SUM))) THREE   -- we've seen this before
    +  =*> ADD THREE (ADD TWO (ADD ONE ZERO))



    How should we define FIX???

    @@ -1854,24 +1885,24 @@

    λ

    The Y combinator

    Remember Ω?

    -
    (\x -> x x) (\x -> x x)
    -=b> (\x -> x x) (\x -> x x)
    +
    (\x -> x x) (\x -> x x)
    +=b> (\x -> x x) (\x -> x x)

    This is self-replicating code! We need something like this but a bit more involved…





    The Y combinator discovered by Haskell Curry:

    -
    let FIX   = \stp -> (\x -> stp (x x)) (\x -> stp (x x))
    +
    let FIX   = \stp -> (\x -> stp (x x)) (\x -> stp (x x))



    How does it work?

    -
    eval fix_step:
    -  FIX STEP
    -  =d> (\stp -> (\x -> stp (x x)) (\x -> stp (x x))) STEP
    -  =b> (\x -> STEP (x x)) (\x -> STEP (x x))
    -  =b> STEP ((\x -> STEP (x x)) (\x -> STEP (x x)))
    -  --       ^^^^^^^^^^ this is FIX STEP ^^^^^^^^^^^
    +
    eval fix_step:
    +  FIX STEP
    +  =d> (\stp -> (\x -> stp (x x)) (\x -> stp (x x))) STEP
    +  =b> (\x -> STEP (x x)) (\x -> STEP (x x))
    +  =b> STEP ((\x -> STEP (x x)) (\x -> STEP (x x)))
    +  --       ^^^^^^^^^^ this is FIX STEP ^^^^^^^^^^^




    diff --git a/docs/lectures/02-haskell.html b/docs/lectures/02-haskell.html index aa02161..016f799 100644 --- a/docs/lectures/02-haskell.html +++ b/docs/lectures/02-haskell.html @@ -291,7 +291,7 @@

    (2) Functions

  • can be returned as results from other functions
  • can be partially applied (arguments passed one at a time)
  • -
    (\f x -> f (f x)) (\z -> z + 1) 0   -- =~> ???
    +
    (\f x -> f (f x)) (\z -> z + 1) 0   -- =~> 2

    But: unlike λ-calculus, not everything is a function!

    (3) Top-level bindings

    Like in Elsa, we can name terms to use them later

    @@ -377,6 +377,7 @@

    QUIZ

    pair x y False = y

    E. C and D


    +

    Answer: E




    @@ -433,6 +434,7 @@

    The scope of variables

    g 0 = False g n = f (n - 1) -- mutual recursion! +

    Answer: f is isEven, g is isOdd




    @@ -440,6 +442,7 @@

    The scope of variables

    haskellIsAwesome = True
     
     haskellIsAwesome = False -- changed my mind
    +

    Answer: no, a variable can be defined once per scope; no mutation!




    @@ -482,6 +485,8 @@

    Types

    What would Elsa say?

    let WEIRDO = ONE ZERO


    +

    Answer: Nothing. When evaluated will crunch to something nonsensical. +lambda-calculus is untyped.




    @@ -489,6 +494,8 @@

    Types

    def weirdo():
       return 0(1)


    +

    Answer: Nothing. When evaluated will cause a run-time error. +Python is dynamically typed.




    @@ -498,6 +505,8 @@

    Types

    zero(1); }


    +

    Answer: Java compiler will reject this. +Java is statically typed.




    @@ -557,7 +566,8 @@

    Function Types

  • if e has type B assuming x has type A
  • For example:

    -
    > :t (\x -> if x then `a` else `b`)  -- ???
    +
    > :t (\x -> if x then `a` else `b`)
    +(\x -> if x then `a` else `b`) :: Bool -> Char




    @@ -588,6 +598,7 @@

    QUIZ

    D. Bool -> String

    E. String -> String -> Bool -> String


    +

    Answer: D




    @@ -646,13 +657,13 @@

    The Type of a List

    myList :: [Int]
     myList = [1,2,3,4]


    -
    -- myList' :: ??
    -myList' = ['h', 'e', 'l', 'l', 'o']
    +
    myList' :: [Char]                   -- or :: String
    +myList' = ['h', 'e', 'l', 'l', 'o'] -- or = "hello"


    -
    -- myList'' :: ???
    -myList'' = [1, 'h']    
    +
    -- myList'' :: Type error: elements have different types!
    +myList'' = [1, 'h']


    -
    -- myList''' :: ???
    +
    myList''' :: [t] -- Generic: works for any type t!
     myList''' = []



    @@ -665,7 +676,9 @@

    The Type of a List

    Functions on lists: range

    -- | List of integers from n upto m
     upto :: Int -> Int -> [Int]
    -upto l u = ???
    +upto l hi + | l > u = [] + | otherwise = l : (upto (l + 1) u)




    @@ -729,6 +742,7 @@

    QUIZ

    D. x is bound to 1, xs is bound to []

    E. x is bound to 1, xs is bound to [1]


    +

    Answer: D




    @@ -759,6 +773,7 @@

    QUIZ

    D. [x+y,1,2]

    E. all of the above


    +

    Answer: D (x+y is a function application, not a constructor application)




    diff --git a/docs/lectures/03-datatypes.html b/docs/lectures/03-datatypes.html index 02ec2b7..b688c8b 100644 --- a/docs/lectures/03-datatypes.html +++ b/docs/lectures/03-datatypes.html @@ -362,6 +362,7 @@

    QUIZ

    >>> volume circ0

    A. 500

    B. Type error

    +

    Answer: A




    @@ -441,6 +442,7 @@

    QUIZ

    C. MkCircle :: Double -> Double -> Circle

    D. MkCircle :: Double -> Double -> Double -> Circle

    E. MkCircle :: (Double, Double, Double) -> Circle

    +

    Answer: D




    @@ -486,6 +488,7 @@

    QUIZ

    >>> volume (MkCuboid 10 20 30)

    A. 6000

    B. Type error

    +

    Answer: B




    @@ -628,6 +631,7 @@

    QUIZ

    B. Circle

    C. MkCircle

    D. (Double, Double, Double)

    +

    Answer: A




    @@ -793,6 +797,7 @@

    QUIZ

    C. (Int, IntList)

    D. Int -> IntList -> IntList

    E. IntList -> IntList

    +

    Answer: D




    @@ -877,6 +882,9 @@

    EXERCISE: Append




    +
    append :: List -> List -> List
    +append Nil ys = ys
    +append (Cons x xs) ys = Cons x (append xs ys)    




    @@ -934,6 +942,7 @@

    QUIZ: Binary trees

    (D) data ITree = ILeaf Int | INode ITree ITree

    (E) data ITree = ILeaf Int | INode Int ITree ITree


    +

    Answer: C




    @@ -947,12 +956,12 @@

    QUIZ: Binary trees

    Binary tree -
    -- | Binary tree of integers
    -data ITree = ILeaf | INode Int ITree ITree
    -
    -t1234 = INode 1 
    -          (INode 2 (INode 3 ILeaf ILeaf) ILeaf) 
    -          (INode 4 ILeaf ILeaf)
    +
    -- | Binary tree of integers
    +data ITree = ILeaf | INode Int ITree ITree
    +
    +t1234 = INode 1 
    +          (INode 2 (INode 3 ILeaf ILeaf) ILeaf) 
    +          (INode 4 ILeaf ILeaf)




    @@ -961,8 +970,9 @@

    QUIZ: Binary trees



    Functions on trees

    -
    height :: Tree -> Int
    -height t = ??
    +
    height :: Tree -> Int
    +height Leaf = 0
    +height (Node _ l r) = 1 + max (height l) (height r)




    @@ -979,7 +989,7 @@

    Example: Calculator

  • (4.0 + 2.9) * (3.78 - 5.92)
  • What is a Haskell datatype to represent these expressions?

    -
    data Expr = ???
    +
    data Expr = ???




    @@ -988,10 +998,10 @@

    Example: Calculator




    -
    data Expr = Num Float
    -          | Add Expr Expr
    -          | Sub Expr Expr
    -          | Mul Expr Expr
    +
    data Expr = Num Float
    +          | Add Expr Expr
    +          | Sub Expr Expr
    +          | Mul Expr Expr




    @@ -1002,13 +1012,16 @@

    Example: Calculator


    EXERCISE: Eval

    With expressions defined as follows:

    -
    data Expr = Num Float
    -          | Add Expr Expr
    -          | Sub Expr Expr
    -          | Mul Expr Expr
    +
    data Expr = Num Float
    +          | Add Expr Expr
    +          | Sub Expr Expr
    +          | Mul Expr Expr

    write a function to evaluate an expression

    -
    eval :: Expr -> Float
    -eval e = ???
    +
    eval :: Expr -> Float
    +eval (Num f)     = f
    +eval (Add e1 e2) = eval e1 + eval e2
    +eval (Sub e1 e2) = eval e1 - eval e2
    +eval (Mul e1 e2) = eval e1 * eval e2




    @@ -1034,13 +1047,13 @@

    Algebraic Data Types

    Parameterized Types

    Our IntList datatype can only store Ints :-(

    What if we want to store Chars or Doubles?

    -
    data CharList 
    -  = CNil
    -  | CCons Char CharList
    -
    -data DoubleList 
    -   = DNil
    -   | DCons Char DoubleList
    +
    data CharList 
    +  = CNil
    +  | CCons Char CharList
    +
    +data DoubleList 
    +   = DNil
    +   | DCons Char DoubleList




    @@ -1068,11 +1081,11 @@

    Don’t Repeat Yourself!


    A Refactored List

    Here are the three types: What is common? What is different?

    -
    data IList = INil | ICons Int    IList
    -
    -data CList = CNil | CCons Char   CList
    -
    -data DList = DNil | DCons Double DList
    +
    data IList = INil | ICons Int    IList
    +
    +data CList = CNil | CCons Char   CList
    +
    +data DList = DNil | DCons Double DList




    @@ -1084,17 +1097,17 @@

    A Refactored List



    Refactored using Type Parameter

    -
    -- | A list of elements of type `a`
    -data List a = Nil | Cons a  (List a)
    +
    -- | A list of elements of type `a`
    +data List a = Nil | Cons a  (List a)

    We can recover original types as instances of List:

    -
    iList :: List Int      -- list where 'a' = 'Int' 
    -iList = Cons 1 (Cons 2 (Cons 3 Nil))
    -
    -cList :: List Char     -- list where 'a' = 'Char' 
    -cList = Cons 'a' (Cons 'b' (Cons 'c' Nil))
    -
    -dList :: List Double   -- list where 'a' = 'Double' 
    -dList = Cons 1.1 (Cons 2.2 (Cons 3.3 Nil))
    +
    iList :: List Int      -- list where 'a' = 'Int' 
    +iList = Cons 1 (Cons 2 (Cons 3 Nil))
    +
    +cList :: List Char     -- list where 'a' = 'Char' 
    +cList = Cons 'a' (Cons 'b' (Cons 'c' Nil))
    +
    +dList :: List Double   -- list where 'a' = 'Double' 
    +dList = Cons 1.1 (Cons 2.2 (Cons 3.3 Nil))




    @@ -1110,13 +1123,14 @@

    Refactored using Type Parameter



    QUIZ

    -
    data List a = Nil | Cons a  (List a)
    +
    data List a = Nil | Cons a  (List a)

    What is the type of Cons ?

    A. Int -> List -> List

    B. Int -> List Int -> List Int

    C. Char -> List Char -> List Char

    D. a -> List -> List

    E. a -> List a -> List a

    +

    Answer: E




    @@ -1153,11 +1167,11 @@

    Type Constructors


    Polymorphic Data has Polymorphic Constructors

    Look at the types of the constructors

    -
    >>> :type Nil 
    -Nil :: List a
    +
    >>> :type Nil 
    +Nil :: List a

    That is, Nil is a value of any kind of list, and

    -
    >>> :type Cons 
    -Cons :: a -> List a -> List a
    +
    >>> :type Cons 
    +Cons :: a -> List a -> List a

    Cons takes an a and a List a and returns a List a.



    @@ -1175,9 +1189,9 @@

    Polymorphic Data has Poly

    Polymorphic Functions

    Let us refactor the append function to work on Lists:

    -
    data List a = Nil | Cons a  (List a)
    -
    append :: ??? -- What is the type of `append`?
    -append = ???
    +
    data List a = Nil | Cons a  (List a)
    +
    append :: ??? -- What is the type of `append`?
    +append = ???




    @@ -1194,9 +1208,9 @@

    Polymorphic Functions


    Polymorphic Functions over Polymorphic Data

    The append function on Lists is polymorphic:

    -
    append :: List a -> List a -> List a
    -append Nil ys         = ys
    -append (Cons x xs) ys = Cons x (append xs ys)
    +
    append :: List a -> List a -> List a
    +append Nil ys         = ys
    +append (Cons x xs) ys = Cons x (append xs ys)

    append doesn’t care about the actual values in the list

    • only manipulates the structure of the list
    • @@ -1206,11 +1220,11 @@

      Polymorphic Functions over
    • we can call append on lists of any kind
    • as long as both lists are of the same kind
    -
    >>> append (Cons 1 (Cons 2 Nil)) (Cons 3 Nil)       -- a = Int
    -Cons 1 (Cons 2 (Cons 3 Nil))
    -
    ->>> append (Cons 'a' (Cons 'b' Nil)) (Cons 'c' Nil)  -- a = Char
    -Cons 'a' (Cons 'b' (Cons 'c' Nil))
    +
    >>> append (Cons 1 (Cons 2 Nil)) (Cons 3 Nil)       -- a = Int
    +Cons 1 (Cons 2 (Cons 3 Nil))
    +
    +>>> append (Cons 'a' (Cons 'b' Nil)) (Cons 'c' Nil)  -- a = Char
    +Cons 'a' (Cons 'b' (Cons 'c' Nil))




    @@ -1229,10 +1243,11 @@

    QUIZ

    With the type of append defined as

    append :: List a -> List a -> List a

    what would be result of

    -
    append (Cons 'a' (Cons 'b' Nil)) (Cons True Nil)
    +
    append (Cons 'a' (Cons 'b' Nil)) (Cons True Nil)

    A. Cons 'a' (Cons 'b' (Cons True Nil))

    B. Cons 'a' (Cons 'b' Nil)

    C. Type error

    +

    Answer: C




    @@ -1249,18 +1264,18 @@

    QUIZ


    Built-in Lists?

    This is exactly how Haskell’s “built-in” lists are defined:

    -
    data [a]    = [] | (:) a [a]
    -
    -data List a = Nil | Cons a (List a)
    +
    data [a]    = [] | (:) a [a]
    +
    +data List a = Nil | Cons a (List a)
    • Nil is called []
    • Cons is called :

    Many list manipulating functions e.g. in Data.List are polymorphic - Can be reused across all kinds of lists.

    -
    (++) :: [a] -> [a] -> [a]
    -head :: [a] -> a
    -tail :: [a] -> [a]
    +
    (++) :: [a] -> [a] -> [a]
    +head :: [a] -> a
    +tail :: [a] -> [a]




    diff --git a/docs/lectures/03-tailrec.html b/docs/lectures/03-tailrec.html index c8f8629..42f8d52 100644 --- a/docs/lectures/03-tailrec.html +++ b/docs/lectures/03-tailrec.html @@ -325,6 +325,7 @@

    QUIZ: Is this function tail recurs

    A. Yes

    B. No


    +

    Answer: B




    @@ -335,7 +336,12 @@

    QUIZ: Is this function tail recurs

    Tail recursive factorial

    Let’s write a tail-recursive factorial!

    facTR :: Int -> Int
    -facTR n = ... 
    +facTR n = loop 1 n + where + loop :: Int -> Int -> Int + loop acc n + | n <= 1 = acc + | otherwise = loop (acc * n) (n - 1)




    diff --git a/docs/lectures/04-hof.html b/docs/lectures/04-hof.html index 60c69f8..6f34648 100644 --- a/docs/lectures/04-hof.html +++ b/docs/lectures/04-hof.html @@ -794,6 +794,7 @@

    QUIZ

    (D) (a -> b -> b) -> b -> [a] -> b

    (E) (b -> a -> b) -> b -> [a] -> b


    +

    Answer: D




    @@ -827,6 +828,7 @@

    QUIZ



    Is foldr tail recursive?

    +

    Answer: No! It calls the binary operations on the results of the recursive call




    diff --git a/site.hs b/site.hs index 0553d48..085f080 100644 --- a/site.hs +++ b/site.hs @@ -49,11 +49,11 @@ main = hakyll $ do match "static/*/*" $ do route idRoute compile copyFileCompiler match (fromList tops) $ crunchWithCtx siteCtx - match "lectures/00-*" $ crunchWithCtxCustom "lecture" postCtx - match "lectures/01-*" $ crunchWithCtxCustom "lecture" postCtx - match "lectures/02-*" $ crunchWithCtxCustom "lecture" postCtx - match "lectures/03-*" $ crunchWithCtxCustom "lecture" postCtx - match "lectures/04-*" $ crunchWithCtxCustom "lecture" postCtx + match "lectures/00-*" $ crunchWithCtxCustom "final" postCtx + match "lectures/01-*" $ crunchWithCtxCustom "final" postCtx + match "lectures/02-*" $ crunchWithCtxCustom "final" postCtx + match "lectures/03-*" $ crunchWithCtxCustom "final" postCtx + match "lectures/04-*" $ crunchWithCtxCustom "final" postCtx match "lectures/05-*" $ crunchWithCtxCustom "lecture" postCtx match "lectures/06-*" $ crunchWithCtxCustom "lecture" postCtx match "lectures/07-*" $ crunchWithCtxCustom "lecture" postCtx