-- AGDA IN PADOVA 2022 -- Exercise sheet 1 -------------------- ----[ BOOLEANS ]---- -------------------- data Bool : Set where false : Bool true : Bool _&&_ : Bool → Bool → Bool false && b = false true && false = false true && true = true -- EXERCISE: Implement boolean "or". -- "false || true" should evaluate to "true". -- "true || true" should evaluate to "true". _||_ : Bool → Bool → Bool false || b = b true || b = true _||'_ : Bool → Bool → Bool false ||' false = false false ||' true = true true ||' b = true -- EXERCISE: Implement a function "is-tautology₁?" which checks whether -- a given input function is constantly true. For instance, if f x = x, -- then "is-tautology₁ f" should evaluate to "false". constantly-true : Bool → Bool constantly-true x = true constantly-true' : Bool → Bool constantly-true' false = true constantly-true' true = true is-tautology₁ : (Bool → Bool) → Bool is-tautology₁ f = f false && f true -- does not work: is-tautology₁ f = f ≡ constantly-true -- in math: is-tautology₁(f) = f(false) && f(true) -- EXERCISE: Implement a function "is-tautology₂?" which checks whether -- a given input function of two arguments is constantly true. For -- instance, if f x y = true, then "is-tautology₂ f" should evaluate to "true". is-tautology₂ : (Bool → Bool → Bool) → Bool is-tautology₂ f = {!!} -- COMMENT: -- Function extensionality means: "If f x = g x for all x, then f = g." --------------------------- ----[ NATURAL NUMBERS ]---- --------------------------- data ℕ : Set where zero : ℕ succ : ℕ → ℕ _+_ : ℕ → ℕ → ℕ zero + b = b succ a + b = succ (a + b) -- EXERCISE: Define the function "half" which divides its input by two. -- For instance "half (succ (succ (succ (succ zero))))" should be "succ (succ zero)" -- and "half (succ (succ (succ zero)))" should be "succ zero" (so we round down). half : ℕ → ℕ half zero = zero half (succ zero) = zero -- in math: half(1) = 0.5 = 0 (rounded down) half (succ (succ n)) = succ (half n) -- (1+n)/2 = 0.5 + n/2 -- (1+1+n)/2 = 1 + n/2 -- EXERCISE: Define (cut-off) subtraction. For instance "succ zero - succ zero" -- and "succ zero - succ (succ zero)" should both be "zero". _-_ : ℕ → ℕ → ℕ a - b = {!!} -- EXERCISE: Define multiplication and exponentiation. -- EXERCISE: Define a function "eq?" which determines whether its two -- input numbers are equal. For instance, "eq? zero zero" should evaluate -- to "true" while "eq? zero (succ zero)" should evaluate to "false". eq? : ℕ → ℕ → Bool eq? a b = {!!} -- EXERCISE: Define a function "≤?" which determines whether its first -- argument is less than or equal to its second. For instance, "≤? -- zero zero" should evaluate to "true" while "≤? (succ zero) zero" -- should evaluate to "false". ≤? : ℕ → ℕ → Bool ≤? a b = {!!} -- EXERCISE: Define a function "even?" which determines whether its input is even. -- For instance, "even? zero" and "even? (succ (succ zero))" should both evaluate to "true", -- while "even? (succ zero)" should evaluate to "false". even? : ℕ → Bool even? zero = true even? (succ zero) = false even? (succ (succ n)) = even? n ¬_ : Bool → Bool ¬ false = true ¬ true = false even?' : ℕ → Bool even?' zero = true even?' (succ n) = ¬ (even?' n) -- EXERCISE: Describe the following type in simple terms. What are its values? data Weird : Set where foo : Weird → Weird -- There are no values of the type Weird! data ∅ : Set where -- \emptyset -- this is the manifestly empty type. empty-function : ∅ → ℕ empty-function () question : ℕ → ∅ question n = {!!} -- this hole is unfillable prior-question : ∅ → ∅ prior-question x = x prior-question' : ∅ → ∅ prior-question' () bonus-question : Weird → ∅ bonus-question (foo x) = bonus-question x -- on to dependent types! -- The type "list of integers" depends on the type of integers, but -- this is still a type (and not a value), and hence the type "list of integers" -- would not usually be called a "dependent type". -- The type "vectors of length n" depends on the number n (which is a value, not a type), -- and hence the type "vectors of length n" would be called a "dependent type". data Vector : ℕ → Set where [] : Vector zero _∷_ : {n : ℕ} → Bool → Vector n → Vector (succ n) example-vector : Vector (succ (succ (succ zero))) example-vector = false ∷ (true ∷ (true ∷ [])) -- [false,true,true] false-vector : {n : ℕ} → Vector n false-vector {zero} = [] false-vector {succ n} = false ∷ false-vector ex : Vector (succ (succ (succ zero))) ex = false-vector -- "false-vector (succ (succ (succ zero)))" should evaluate to "false ∷ (false ∷ (false ∷ [])))" data Vector' (A : Set) : ℕ → Set where [] : Vector' A zero _∷_ : {n : ℕ} → A → Vector' A n → Vector' A (succ n) -- for instance, Vector' Bool (succ (succ zero)) is the type of boolean vectors of length 2. -- for instance, Vector' ℕ (succ (succ zero)) is the type of vectors of length 2 whose entries are natural numbers. data Vector'' : Set → ℕ → Set where [] : {A : Set} → Vector'' A zero _∷_ : {A : Set} {n : ℕ} → A → Vector'' A n → Vector'' A (succ n) -- ♥ : Vector'' Bool (succ (succ zero)) -- for instance, "map f (x ∷ (y ∷ (z ∷ [])))" should evaluate to "f x ∷ (f y ∷ (f z ∷ []))". -- map : {A : Set} → {B : Set} → {n : ℕ} → (A → B) → Vector' A n → Vector' B n map : {A B : Set} {n : ℕ} → (A → B) → Vector' A n → Vector' B n map f [] = [] map f (x ∷ xs) = f x ∷ map f xs -- Set is the type of all small types; it's the "universe". -- for instance, ℕ : Set -- for instance, Bool : Set -- for instance, ∅ : Set -- zero : ℕ : Set : Set₁ : Set₂ : Set₃ : Set₄ : ... -- Agda has a mode to switch it as follows: zero : ℕ : Set : Set : Set : Set : Set : ... -- The resulting system will be inconsistent (be able to prove 1 = 0). -- ℕ is actually a value of type Set. :-)