packages feed

Agda-2.3.2.2: examples/SummerSchool07/Solutions/Problem4.agda

module Problem4 where

infixr 40 _::_

data List (A : Set) : Set where
  []   : List A
  _::_ : A -> List A -> List A

-- 4.1

map : {A B : Set} -> (A -> B) -> List A -> List B
map f []        = []
map f (x :: xs) = f x :: map f xs

infixr 40 _++_

_++_ : {A : Set} -> List A -> List A -> List A
[]        ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)

-- 4.2

infixr 40 _▹_

data All {A : Set}(P : A -> Set) : List A -> Set where
  ∅   : All P []
  _▹_ : {x : A} -> P x -> {xs : List A} -> All P xs -> All P (x :: xs)

-- 4.3

data Some {A : Set}(P : A -> Set) : List A -> Set where
  hd : {x : A} -> P x -> {xs : List A}   -> Some P (x :: xs)
  tl : {x : A}{xs : List A} -> Some P xs -> Some P (x :: xs)

-- 4.4

-- We need composition at a higher universe here.

_∘¹_ : {A B : Set}{C : B -> Set1}(f : (x : B) -> C x)
       (g : A -> B)(x : A) -> C (g x)
(f ∘¹ g) x = f (g x)

-- You might have to give f explictly when applying this theorem.

all-map : {A B : Set}{P : A -> Set}{Q : B -> Set}{f : A -> B}{xs : List A} ->
          ({x : A} -> P x -> Q (f x)) ->
          All P xs -> All Q (map f xs)
all-map h ∅        = ∅
all-map h (p ▹ ps) = h p ▹ all-map h ps

all-++ : {A : Set}{P : A -> Set}{xs ys : List A} ->
         All P xs -> All P ys -> All P (xs ++ ys)
all-++ ∅        qs = qs
all-++ (p ▹ ps) qs = p ▹ (all-++ ps qs)

some-map : {A B : Set}{P : A -> Set}{Q : B -> Set}{f : A -> B}{xs : List A} ->
           ({x : A} -> P x -> Q (f x)) ->
           Some P xs -> Some Q (map f xs)
some-map h (hd p)  = hd (h p)
some-map h (tl ps) = tl (some-map h ps)

some-++-left : {A : Set}{P : A -> Set}{xs ys : List A} ->
               Some P xs -> Some P (xs ++ ys)
some-++-left (hd p)  = hd p
some-++-left (tl ps) = tl (some-++-left ps)

-- Here we can't expect to infer xs, so we make it explicit

some-++-right : {A : Set}{P : A -> Set}(xs : List A){ys : List A} ->
               Some P ys -> Some P (xs ++ ys)
some-++-right []        p = p
some-++-right (x :: xs) p = tl (some-++-right xs p)

-- 4.5

data _==_ {A : Set}(x : A) : A -> Set where
  refl : x == x

_∈_ : {A : Set} -> A -> List A -> Set
x ∈ xs = Some (_==_ x) xs

-- 4.6

record True : Set where

tt : True
tt = record {}

Nat  = List True

zero : Nat
zero = []

suc : Nat -> Nat
suc n = tt :: n

Vec : Set -> Nat -> Set
Vec A n = All (\_ -> A) n

Fin : Nat -> Set
Fin n = Some (\_ -> True) n

-- 4.7

infixr 5 _,_

data _×_ (A : Set)(B : A -> Set) : Set where
  _,_ : (x : A) -> B x -> A × B

_∧_ : Set -> Set -> Set
A ∧ B = A × (\_ -> B)

_!_ : {A : Set}{P : A -> Set}{Q : A -> Set}{xs : List A} ->
      All P xs -> Some Q xs -> A × (\z -> P z ∧ Q z)
∅ ! ()
(p ▹ ps) ! hd q = (_ , p , q)
(p ▹ ps) ! tl q = ps ! q

-- 4.8

data False : Set where

¬_ : Set -> Set
¬ A = A -> False

data _∨_ (A B : Set) : Set where
  inl : A -> A ∨ B
  inr : B -> A ∨ B

data Bool : Set where
  true  : Bool
  false : Bool

data IsTrue : Bool -> Set where
  isTrue : IsTrue true

Holds : {A : Set} -> (A -> Bool) -> A -> Set
Holds p x = IsTrue (p x)

false-isn't-true : ¬ IsTrue false
false-isn't-true ()

decide : {A : Set}(p : A -> Bool)(x : A) ->
         Holds p x ∨ ¬ Holds p x
decide p x with p x
...        | true  = inl isTrue
...        | false = inr false-isn't-true

all : {A : Set}(p : A -> Bool)(xs : List A) ->
      All (Holds p) xs ∨ Some (\x -> ¬ Holds p x) xs
all p [] = inl ∅
all p (x :: xs) with decide p x
... | inr npx = inr (hd npx)
... | inl px  with all p xs
...   | inr npxs = inr (tl npxs)
...   | inl pxs  = inl (px ▹ pxs)