{-# OPTIONS --allow-unsolved-metas #-}
-- AGDA IN PADOVA 2023
-- 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
-- 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".
is-tautology₁ : (Bool → Bool) → Bool
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 =
-- f false false && (f false true && (f true false && f true true))
is-tautology₂ f = is-tautology₁ (f false) && is-tautology₁ (f true)
---------------------------
----[ NATURAL NUMBERS ]----
---------------------------
data ℕ : Set where
zero : ℕ
succ : ℕ → ℕ
_+_ : ℕ → ℕ → ℕ
zero + b = b
succ a + b = succ (a + b)
-- Informally:
-- succ a + b = (1+a) + b = 1 + a + b = 1+(a+b) = succ (a + b)
data ListOfNats : Set where
[] : ListOfNats
_∷_ : ℕ → ListOfNats → ListOfNats
exampleList : ListOfNats
exampleList = zero ∷ (succ (succ zero) ∷ (succ zero ∷ [])) -- \:: "cons"
-- Haskell notation: [zero, succ (succ zero), succ zero]
data ListOfBooleans : Set where
[] : ListOfBooleans
_∷_ : Bool → ListOfBooleans → ListOfBooleans
-- The following type introduces, for each type "X", a new type "List X".
data List (X : Set) : Set where
[] : List X
_∷_ : X → List X → List X
exampleListOfBooleans : List Bool
exampleListOfBooleans = false ∷ (true ∷ (false ∷ (false ∷ [])))
exampleListOfLists : List (List Bool)
exampleListOfLists = exampleListOfBooleans ∷ (exampleListOfBooleans ∷ [])
-- 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 n = {!!}
-- 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? n = {!!}
-- EXERCISE: Describe the following type in simple terms. What are its values?
-- This type is empty. It does not have any inhabitants.
-- The constructor "foo" is not applicable, because we can only
-- use it in case we already have a value of type "Weird" at hand,
-- which we don't.
data Weird : Set where
foo : Weird → Weird
data Empty : Set where
-- This type is manifestly empty.
-- The following hole can NOT be filled:
f : ℕ → Empty
f n = {!!}
g : Empty → Empty
g x = x
-- There is a function from X to Empty only in the case that
-- X itself is an empty type.
h : Weird → Empty
h (foo x) = h x
{-
data Lol : Set where
bar : {!(Empty → Lol) → Lol!}
-}
data Bar : Set where
hello : Empty → Bar