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 @@
The Turing Machine
The Lambda Calculus
@@ -473,6 +475,7 @@
D. A and C
E. all of the above
Correct answer: A
@@ -678,6 +681,7 @@
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 @@
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 @@
What is the shortest closed expression?
+Answer: \x -> x
@@ -782,7 +787,7 @@
-> f (\x -> x)) (give apple)
- (\f =b> ???
@@ -805,6 +810,7 @@
D. \y -> y
E. \x -> y
Correct answer: D.
@@ -826,6 +832,7 @@
D. apple
E. \x -> x
Correct answer: A.
@@ -894,6 +901,9 @@
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 @@
-- (A)
-> f x =a> \x -> x x \f
Answer: it violates the side-condition that the new formal (x
) must not occur freely in the body
-- (B)
-> \y -> y) y =a> (\x -> \z -> z) z (\x
Answer: we should only rename within the body of the abstraction; the second y
is a free variable, and hence must remain unchanged
-- (C)
-> (\y -> x y) =a> \y -> (\y -> y y) \x
Answer: the new formal y
does not occur freely in the body, but the substitution is not capture-avoiding
@@ -964,7 +977,8 @@
-> (\y -> x)) y
- (\x =a> ???
To avoid getting confused, you can always rename formals, so that different variables have different names!
@@ -1004,6 +1018,7 @@C. x (\y -> y) z
D. x ((\y -> y) z)
E. B and D
+Answer: E
@@ -1037,8 +1052,9 @@
-> x) apple
(\x =b> apple
-> (\x -> x) f) (\x -> x)
- (\f =?> ???
-> f (\x -> x)) (\x -> x)
+ (\f =b> (\x -> x) (\x -> x)
+ =b> \x -> x
:
- eval ite_falseITE FALSE egg ham
-
--- fill the steps in!
-
-=b> ham
:
+ eval ite_falseITE 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 @@
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_tNOT TRUE =*> FALSE
-
- :
- eval ex_not_fNOT FALSE =*> TRUE
-
- :
- eval ex_or_ffOR FALSE FALSE =*> FALSE
-
-:
- eval ex_or_ftOR FALSE TRUE =*> TRUE
-
- :
- eval ex_or_ftOR TRUE FALSE =*> TRUE
-
-:
- eval ex_or_ttOR TRUE TRUE =*> TRUE
-
- :
- eval ex_and_ffAND FALSE FALSE =*> FALSE
-
-:
- eval ex_and_ftAND FALSE TRUE =*> FALSE
-
- :
- eval ex_and_ftAND TRUE FALSE =*> FALSE
-
-:
- eval ex_and_ttAND TRUE TRUE =*> TRUE
:
+ eval ex_not_tNOT TRUE =*> FALSE
+
+ :
+ eval ex_not_fNOT FALSE =*> TRUE
+
+ :
+ eval ex_or_ffOR FALSE FALSE =*> FALSE
+
+:
+ eval ex_or_ftOR FALSE TRUE =*> TRUE
+
+ :
+ eval ex_or_ftOR TRUE FALSE =*> TRUE
+
+:
+ eval ex_or_ttOR TRUE TRUE =*> TRUE
+
+ :
+ eval ex_and_ffAND FALSE FALSE =*> FALSE
+
+:
+ eval ex_and_ftAND FALSE TRUE =*> FALSE
+
+ :
+ eval ex_and_ftAND TRUE FALSE =*> FALSE
+
+:
+ eval ex_and_ttAND TRUE TRUE =*> TRUE
@@ -1369,18 +1393,18 @@
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_fstFST (PAIR apple banana) =~> apple
-
-:
- eval ex_sndSND (PAIR apple banana) =~> banana
:
+ eval ex_fstFST (PAIR apple banana) =~> apple
+
+:
+ eval ex_sndSND (PAIR apple banana) =~> banana
@@ -1396,9 +1420,9 @@
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 @@
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 ex1FST3 (TRIPLE apple banana orange)
- =~> apple
-
-:
- eval ex2SND3 (TRIPLE apple banana orange)
- =~> banana
-
-:
- eval ex3THD3 (TRIPLE apple banana orange)
- =~> orange
let TRIPLE = \x y z -> ???
+let FST3 = \t -> ???
+let SND3 = \t -> ???
+let THD3 = \t -> ???
+
+:
+ eval ex1FST3 (TRIPLE apple banana orange)
+ =~> apple
+
+:
+ eval ex2SND3 (TRIPLE apple banana orange)
+ =~> banana
+
+:
+ eval ex3THD3 (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 @@
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 @@
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)))))
+...
Which of these is a reasonable encoding of ZERO
?
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 @@
-- 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 @@
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_zeroADD ZERO ZERO =~> ZERO
-
-:
- eval add_zero_oneADD ZERO ONE =~> ONE
-
-:
- eval add_zero_twoADD ZERO TWO =~> TWO
-
-:
- eval add_one_zeroADD ONE ZERO =~> ONE
-
-:
- eval add_one_zeroADD ONE ONE =~> TWO
-
-:
- eval add_two_zeroADD 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_zeroADD ZERO ZERO =~> ZERO
+
+:
+ eval add_zero_oneADD ZERO ONE =~> ONE
+
+:
+ eval add_zero_twoADD ZERO TWO =~> TWO
+
+:
+ eval add_one_zeroADD ONE ZERO =~> ONE
+
+:
+ eval add_one_zeroADD ONE ONE =~> TWO
+
+:
+ eval add_two_zeroADD TWO ZERO =~> TWO
@@ -1616,15 +1646,15 @@
λ-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 @@
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 @@
-- 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 @@
I want to write a function that sums up natural numbers up to n
:
-> ... -- 0 + 1 + 2 + ... + n \n
-> ... -- 0 + 1 + 2 + ... + n \n
@@ -1714,9 +1745,9 @@
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 @@
-> ITE (ISZ n)
- \n ZERO
- ADD n (SUM (DEC n))) -- But SUM is not a thing! (
-> ITE (ISZ n)
+ \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 =
--> \n -> ITE (ISZ n)
- \rec ZERO
- ADD n (rec (DEC n))) -- Call some rec (
let STEP =
+-> \n -> ITE (ISZ n)
+ \rec 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 @@
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_threeSUM 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_threeSUM 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
???
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_stepFIX 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_stepFIX 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 @@
-> f (f x)) (\z -> z + 1) 0 -- =~> ??? (\f x
-> f (f x)) (\z -> z + 1) 0 -- =~> 2 (\f x
But: unlike λ-calculus, not everything is a function!
Like in Elsa, we can name terms to use them later
@@ -377,6 +377,7 @@E. C and D
Answer: E
@@ -433,6 +434,7 @@
Answer: f
is isEven
, g
is isOdd
= True
haskellIsAwesome
= False -- changed my mind haskellIsAwesome
Answer: no, a variable can be defined once per scope; no mutation!
@@ -482,6 +485,8 @@
What would Elsa say?
let WEIRDO = ONE ZERO
Answer: Nothing. When evaluated will crunch to something nonsensical. +lambda-calculus is untyped.
def weirdo():
return 0(1)
Answer: Nothing. When evaluated will cause a run-time error. +Python is dynamically typed.
Answer: Java compiler will reject this. +Java is statically typed.
@@ -557,7 +566,8 @@
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`)
+-> if x then `a` else `b`) :: Bool -> Char (\x
@@ -588,6 +598,7 @@
D. Bool -> String
E. String -> String -> Bool -> String
Answer: D
@@ -646,13 +657,13 @@
myList :: [Int]
= [1,2,3,4] myList
-- myList' :: ??
-= ['h', 'e', 'l', 'l', 'o'] myList'
myList' :: [Char] -- or :: String
+= ['h', 'e', 'l', 'l', 'o'] -- or = "hello" myList'
-- myList'' :: ???
-= [1, 'h'] myList''
-- myList'' :: Type error: elements have different types!
+= [1, 'h'] myList''
-- 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 @@
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 @@
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 @@
>>> volume circ0
A. 500
B. Type error
+Answer: A
@@ -441,6 +442,7 @@
C. MkCircle :: Double -> Double -> Circle
D. MkCircle :: Double -> Double -> Double -> Circle
E. MkCircle :: (Double, Double, Double) -> Circle
Answer: D
@@ -486,6 +488,7 @@
>>> volume (MkCuboid 10 20 30)
A. 6000
B. Type error
+Answer: B
@@ -628,6 +631,7 @@
B. Circle
C. MkCircle
D. (Double, Double, Double)
Answer: A
@@ -793,6 +797,7 @@
C. (Int, IntList)
D. Int -> IntList -> IntList
E. IntList -> IntList
Answer: D
@@ -877,6 +882,9 @@
append :: List -> List -> List
+Nil ys = ys
+ append Cons x xs) ys = Cons x (append xs ys) append (
@@ -934,6 +942,7 @@
(D) data ITree = ILeaf Int | INode ITree ITree
(E) data ITree = ILeaf Int | INode Int ITree ITree
Answer: C
@@ -947,12 +956,12 @@
-- | Binary tree of integers
-data ITree = ILeaf | INode Int ITree ITree
-
-= INode 1
- t1234 INode 2 (INode 3 ILeaf ILeaf) ILeaf)
- (INode 4 ILeaf ILeaf) (
-- | Binary tree of integers
+data ITree = ILeaf | INode Int ITree ITree
+
+= INode 1
+ t1234 INode 2 (INode 3 ILeaf ILeaf) ILeaf)
+ (INode 4 ILeaf ILeaf) (
@@ -961,8 +970,9 @@
height :: Tree -> Int
-= ?? height t
height :: Tree -> Int
+Leaf = 0
+ height Node _ l r) = 1 + max (height l) (height r) height (
@@ -979,7 +989,7 @@
(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 @@
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 @@
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
+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 eval (
@@ -1034,13 +1047,13 @@
Our IntList
datatype can only store Int
s :-(
What if we want to store Char
s or Double
s?
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 @@
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 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'
-= Cons 1 (Cons 2 (Cons 3 Nil))
- iList
-cList :: List Char -- list where 'a' = 'Char'
-= Cons 'a' (Cons 'b' (Cons 'c' Nil))
- cList
-dList :: List Double -- list where 'a' = 'Double'
-= Cons 1.1 (Cons 2.2 (Cons 3.3 Nil)) dList
iList :: List Int -- list where 'a' = 'Int'
+= Cons 1 (Cons 2 (Cons 3 Nil))
+ iList
+cList :: List Char -- list where 'a' = 'Char'
+= Cons 'a' (Cons 'b' (Cons 'c' Nil))
+ cList
+dList :: List Double -- list where 'a' = 'Double'
+= Cons 1.1 (Cons 2.2 (Cons 3.3 Nil)) dList
@@ -1110,13 +1123,14 @@
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 @@
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 @@
Let us refactor the append
function to work on List
s:
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 @@
The append
function on List
s is polymorphic:
append :: List a -> List a -> List a
-Nil ys = ys
- append Cons x xs) ys = Cons x (append xs ys) append (
append :: List a -> List a -> List a
+Nil ys = ys
+ append Cons x xs) ys = Cons x (append xs ys) append (
append
doesn’t care about the actual values in the list
append
on lists of any 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 @@
With the type of append
defined as
append :: List a -> List a -> List a
what would be result of
-Cons 'a' (Cons 'b' Nil)) (Cons True Nil) append (
Cons 'a' (Cons 'b' Nil)) (Cons True Nil) append (
A. Cons 'a' (Cons 'b' (Cons True Nil))
B. Cons 'a' (Cons 'b' Nil)
C. Type error
+Answer: C
@@ -1249,18 +1264,18 @@
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 @@
A. Yes
B. No
Answer: B
@@ -335,7 +336,12 @@
Let’s write a tail-recursive factorial!
facTR :: Int -> Int
-= ... facTR n
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 @@
(D) (a -> b -> b) -> b -> [a] -> b
(E) (b -> a -> b) -> b -> [a] -> b
Answer: D
@@ -827,6 +828,7 @@
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