Tutorial (Week 2)
Table of Contents
1. Predicate Logic
1.1. Question 1
For which values of \(A\) and \(B\) does the boolean expression \(\varphi = \neg (A \Rightarrow B) \lor \neg B\) hold?
(todo)
1.2. Question 2
A binary connective \(\bullet\) is defined as follows:
| \(A\) | \(B\) | \(A\ \bullet\ B\) |
| \(\bot\) | \(\bot\) | \(\top\) |
| \(\bot\) | \(\top\) | \(\bot\) |
| \(\top\) | \(\bot\) | \(\top\) |
| \(\top\) | \(\top\) | \(\top\) |
(The syntax \(\bot\) is one way of typesetting "False", ditto \(\top\) for "True".)
Restate the formula \(A \lor B\) in terms of \(\bullet\). What is the \(\bullet\) connective?
(todo)
1.3. Question 3
Assuming that \(F(x)\) states that the person \(x\) is my friend and that \(P(x)\) states that the person \(x\) is perfect, what is a logical translation of the phrase "None of my friends are perfect"?
(todo)
2. Haskell
Write a Haskell function
mySumthat sums all elements in a list of numbers. Feel free to use the following template:mySum :: [Int] -> Int mySum [] = ??? mySum (n:ns) = ???
- Write a Haskell function
myProductthat multiplies all elements in a list of numbers. You probably used copypaste to solve the previous question, didn't you? No reason to be ashamed, we've all done it! But let's try not to.
Find a generalisation
myBinopthat applies a given binary operatorfwith unit elementzto a list of numbers. We will then be able to definemyProductandmySumusingmyBinop.myBinop :: (Int -> Int -> Int) -> Int -> ([Int] -> Int) myBinop f z [] = ??? myBinop f z (n:ns) = ??? mySum :: [Int] -> Int mySum ns = myBinop (+) 0 ns myProduct :: [Int] -> Int myProduct ns = myBinop (*) 1 ns
We just reinvented a wheel. The fold functions are general-purpose library functions that completely subsume
myBinop. Try to implementmySumandmyProductusingfoldrinstead ofmyBinop.The linked library documentation references a lot of concepts that we don't assume familiarity with, so don't worry if you don't fully understand it. Perhaps start by looking at the examples.
(todo)
3. Inductive Types
Consider the (++) operator in Haskell.
(++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x : (xs ++ ys)
- State the formal properties of left identity, right identity and associativity
for
(++). - Try to prove these properties. In some cases, you may
need to perform induction on the structure of lists. The base case of the induction will be for the empty list, and the inductive case
will be to show your property for a list
(x:xs), assuming the property for the listxs(this assumption is called the inductive hypothesis).
(todo)
4. Inference Rules (and Red Black Trees)
Red-black trees are binary search trees where each node in the tree is coloured either red or black. In C, red-black trees could, for example, be encoded with the following user-defined data type:
typedef struct redBlackNode* link; struct redBlackNode { Item item; // Item type defined elsewhere link left, right; int isRed; // 1 if node is red, 0 if black };
and in Haskell (again, we assume the Item type is defined elsewhere)
data RBColour = Red | Black data RBTree = RBLeaf | RBNode RBColour Item RBTree RBTree
- The user defined Haskell data type characterises a set of terms as
RBTree. List the inference rules to define the same set. Assume there already exists a judgement \(x\ \mathbf{Item}\) which is derivable for all \(x\) in theItemtype. - In a proper red-black tree, we can never have a red parent node with a red child, although it is possible to have black nodes with black children. Moreover, the root node cannot be red. Therefore, not all terms of type
RBTreeare real red-black trees. Define inference rules for a property \(t\ \mathbf{OK}\), such that \(\mathbf{OK}\) is derivable if the term \(t\) represents a proper red-black tree.
(todo)