# Proposal for a plan

- Polymorphic data types
- More Even/Odd
- Equality
- State and prove lemmas about natural numbers involving equality (e.g. x + y = y + x)
- Logical connectives: ¬, ∧, ∨, ∃, ...

```
data  : Set where
  zero : 
  succ :   

data Bool : Set where
  false : Bool
  true  : Bool

infixr 5 _∷_
data ListOfNats : Set where
  []  : ListOfNats
  _∷_ :   ListOfNats  ListOfNats

exampleList : ListOfNats
exampleList = zero  zero  succ (succ zero)  zero  []

data ListOfBools : Set where
  []  : ListOfBools
  _∷_ : Bool  ListOfBools  ListOfBools

-- `List` will be a function of type Set → Set; this function reads a type `X`
-- as input and outputs the type of lists of elements of `X`.
data List (X : Set) : Set where   -- a "parameterized definition"
  []  : List X
  _∷_ : X  List X  List X

data List' : Set  Set₁ where   -- an "indexed definition"
  []  : {X : Set}  List' X
  _∷_ : {X : Set}  X  List' X  List' X

data Weird : Set where
  succ : Weird  Weird
-- This type is empty.
-- The constructor `succ` reads as input an inhabitant of type `Weird`
-- and outputs a new freshly-minted inhabitant of type `Weird`.
-- However, this constructor is of no use, as we don't have any inhabitants
-- of type `Weird` to begin with.

-- The following definition is not accepted by Agda's termination checker:
-- foo : Weird
-- foo = succ foo
-- spelled out: succ (succ (succ (succ ...)))
-- We need to turn to so-called co-datatypes to have something like this work.

-- Let's define the type `Vec ℕ three` of vectors of natural numbers of length precisely three.
-- More generally, for every number `n` and for every small type `X`, let's define
-- the type `Vec X n` of vectors of elements of `X` of length precisely `n`.
data Vec (X : Set) :   Set where
  []  : Vec X zero
  _∷_ : {n : }  X  Vec X n  Vec X (succ n)

three : 
three = succ (succ (succ zero))

example-vector : Vec  three
example-vector = succ zero  zero  succ (succ zero)  []

_+_ :     
zero   + y = y
succ x + y = succ (x + y)

-- The concatenation operator. For instance, `example-vector ++ example-vector`
-- should result in `succ zero ∷ zero ∷ succ (succ zero) ∷ succ zero ∷ zero ∷ succ (succ zero) ∷ []`.
_++_ : {X : Set} {n m : }  Vec X n  Vec X m  Vec X (n + m)
[]       ++ ys = ys
(x  xs) ++ ys = x  (xs ++ ys)

data Even :   Set where
  base-even : Even zero
  step-even : {n : }  Even n  Even (succ (succ n))

-- Logical reading: For every number x, for every number y, if x is
-- even, and if y is even, then x + y is even.
-- Computational reading: `sum-even` is a function which inputs
-- 1. a number `x` (implicit)
-- 2. a number `y` (implicit)
-- 3. a witness that `x` is even
-- 4. a witness that `y` is even
-- and which outputs a witness that `x + y` is even.
sum-even : {x y : }  Even x  Even y  Even (x + y)
sum-even base-even     q = q
sum-even (step-even p) q = step-even (sum-even p q)

-- Equality! :-)
two : 
two = succ (succ zero)

four : 
four = succ (succ (succ (succ zero)))

-- {-# BUILTIN NATURAL ℕ #-}
-- meaning-of-life : ℕ
-- meaning-of-life = 42

-- For every type X, and for every inhabitant a : X, and for every inhabitant b : X,
-- there is the type `a ≡ b` of witnesses that `a` equals `b`.
-- For instance, the type `two + two ≡ four` is inhabited, while the type `two + two ≡ zero`
-- is empty.

infix 4 _≡_
data _≡_ {X : Set} : X  X  Set where
  refl : {x : X}  x  x
  -- bailout : two + two ≡ zero

grande-teorema : two + two  four  -- \==
grande-teorema = refl
-- We can use `refl` if and only if it's obvious to Agda (by unfolding the definitions,
-- i.e. by running the code as far as possible) that the two sides of
-- the equation are the same.

-- Logical reading: For every number y, zero + y equals y.
-- Computational reading: `thm` is a function which inputs a number `y` and
-- which outputs a witness that `zero + y` equals `y`.
thm : (y : )  zero + y  y
thm y = refl

-- Logical reading: For every small type X, for every small type Y,
-- for every elements a, b : X, for every function f : X → Y, if `a`
-- equals `b`, then also `f a` equals `f b`.
-- Computational reading: `cong` is a function which inputs
-- 1. a small type X (implicitly)
-- 2. a small type Y (implicitly)
-- 3. an element a : X (implicitly)
-- 4. an element b : X (implicitly)
-- 5. a function f : X → Y
-- 6. a witness that a equals b
-- and which outputs a witness that f a equals f b.
cong : {X Y : Set} {a b : X} (f : X  Y)  a  b  f a  f b
cong f refl = refl

sym : {X : Set} {a b : X}  a  b  b  a
sym refl = refl

+-zero : (y : )  y + zero  y
+-zero zero     = refl
+-zero (succ y) = cong succ (+-zero y)

+-succ : (x y : )  (x + succ y)  succ (x + y)
+-succ zero     y = refl
+-succ (succ x) y = cong succ (+-succ x y)

-- Agda is a calculator, but not for numbers, and instead for logic!

trans : {X : Set} {a b c : X}  a  b  b  c  a  c
trans = ?

+-comm : (x y : )  x + y  y + x
+-comm zero     y = sym (+-zero y)
+-comm (succ x) y = trans (sym (+-succ x y)) (trans (+-comm x (succ y)) (sym (+-succ y x)))
```