packages feed

hoq-0.1.0.0: examples/basics.hoq

-- Pi types
id : (A : Type) -> A -> A
id A a = a

-- Universes
-- Type and Type0 are synonyms
universes : (f : Type1 -> Type0) -> f Type0 -> f Type0
universes f = id (f Type0)

-- Universes are cumulative
cumulative : Type3 -> Type8
cumulative A = A

-- Lambdas
compose : (A B C : Type) -> (B -> C) -> (A -> B) -> A -> C
compose A B C = \g f a -> g (f a)

-- Data types
data Bool = false | true

data Nat = zero | suc Nat

data List (A : Type) = nil | cons A (List A)

-- Pattern matching
not : Bool -> Bool
not true = false
not false = true

and : Bool -> Bool -> Bool
and true true = true
and _ _ = false

-- Recursive functions
plus : Nat -> Nat -> Nat
plus zero y = y
plus (suc x) y = suc (plus x y)

ack : Nat -> Nat -> Nat
ack zero n = suc n
ack (suc m) zero = ack m (suc zero)
ack (suc m) (suc n) = ack m (ack (suc m) n)

-- Interval type
-- I is a type with constructors left : I and right : I
-- coe and squeeze are primitive operators which satisfy the following rules:
-- 
-- coe : (A : I -> Type) (i : I) -> A i -> (j : I) -> A j
-- coe A i a i = a
-- coe (\_ -> A) i a j = a
-- 
-- squeeze : I -> I -> I
-- squeeze left _ = left
-- squeeze right j = j
-- squeeze _ left = left
-- squeeze i right = i

-- Path types
-- Path A a a' is a type with constructor path : (f : (i : I) -> A i) -> Path A (f left) (f right)
-- a = a' is a synonym for Path (\_ -> A) a a'
-- @ is an eliminator for Path, it has type Path A a a' -> (i : I) -> A i
-- path f @ i = f i

idp : (A : Type) (a : A) -> a = a
idp A a = path (\_ -> a)

transport : (A : Type) (B : A -> Type) (a a' : A) -> a = a' -> B a -> B a'
transport A B _ _ p x = coe (\i -> B (p @ i)) left x right

J : (A : Type) (B : (a a' : A) -> a = a' -> Type) -> ((a : A) -> B a a (idp A a)) -> (a a' : A) (p : a = a') -> B a a' p
J A B d a a' p = coe (\i -> B a (p @ i) (path (\j -> p @ squeeze i j))) left (d a) right

ext : (A : Type) (B : A -> Type) (f g : (a : A) -> B a) -> ((a : A) -> f a = g a) -> f = g
ext A B f g p = path (\i a -> p a @ i)

-- Univalence
not-not : (x : Bool) -> not (not x) = x
not-not true  = idp Bool true
not-not false = idp Bool false

biso : Bool = Bool
biso = path (iso Bool Bool not not not-not not-not)

-- coe satisfies the following rules:
-- coe (iso A B f g p q) left a right = f a
-- coe (iso A B f g p q) right b left = g b
biso-not : coe (\i -> biso @ i) left true right = false
biso-not = idp Bool false

biso-not-not : coe (\i -> biso @ i) right (coe (\i -> biso @ i) left true right) left = true
biso-not-not = idp Bool true

-- Data types with conditions
data Z = positive Nat | negative Nat with
    negative zero = positive zero

-- Now, this works,
succ : Z -> Z
succ (positive x)       = positive (suc x)
succ (negative zero)    = positive (suc zero)
succ (negative (suc x)) = negative x

-- but this don't
succ' : Z -> Z
succ' (positive x)       = positive (suc x)
succ' (negative zero)    = positive zero
succ' (negative (suc x)) = negative x

-- We can define higher inductive types using data types with conditions and the interval object
data Circle = base | loop I with
    loop left  = base
    loop right = base

Circle-elim : (P : Circle -> Type) (b : P base) -> Path (\i -> P (loop i)) b b -> (x : Circle) -> P x
Circle-elim P b t base     = b
Circle-elim P b t (loop i) = t @ i

Circle-elim' : (P : Circle -> Type) (b : P base) -> transport Circle P base base (path loop) b = b -> (x : Circle) -> P x
Circle-elim' P b t base     = b
Circle-elim' P b t (loop i) = 
    coe  (\j -> Path (\k -> P (loop k)) b (t @ j)) left
    (path (\j -> coe (\k -> P (loop k)) left b j)) right @ i