----------------------------------------------------------------------
-- Various types and functions
--
-- Nils Anders Danielsson & Patrik Jansson
----------------------------------------------------------------------

module Prelude where

----------------------------------------------------------------------
-- Equality

-- Equality. Note that this definition is very similar to the one
-- given in AFP 2012 Lecture 7 in Typed.hs.

infix 4 _≡_

data _≡_ {A : Set} (x : A) : A  Set where
  refl : x  x

-- Symmetry. Agda checks [*] that all cases are covered, and that the
-- function is terminating/productive, because otherwise one could
-- prove anything.
--
-- [*] Unless the Agda implementation is buggy.

sym :  {A} {x y : A}    x  y    y  x
sym refl = refl

-- Transitivity.

trans :  {A} {x y z : A}    x  y    y  z    x  z
trans refl refl = refl

-- Equality is a congruence: every function preserves equality.

cong :  {A B} (f : A  B) {x y}    x  y    f x  f y
cong f refl  =  refl

cong₂ :  {A B C} (f : A  B  C) {x y u v} 
        x  y    u  v    f x u  f y v
cong₂ f refl refl  =  refl

----------------------------------------------------------------------
-- The unit type

data Unit : Set where
  unit : Unit

----------------------------------------------------------------------
-- The Maybe type

data Maybe (A : Set) : Set where
  just     :  A  Maybe A
  nothing  :  Maybe A

-- Applicative functor application.

infixl 4  _<$>_   _⊛_

_⊛_ :  {A B}  Maybe (A  B)  Maybe A  Maybe B
just f   just x   =  just (f x)
just f   nothing  =  nothing
nothing  _        =  nothing

-- Map.

_<$>_ :  {A B}  (A  B)  Maybe A  Maybe B
f <$> mx  =  just f    mx

-- A safe variant of fromJust. If the value is nothing, then the
-- return type is the unit type.

FromJust :  A  Maybe A  Set
FromJust A (just _) = A
FromJust A nothing  = Unit

fromJust :  {A} (x : Maybe A)  FromJust A x
fromJust (just x) = x
fromJust nothing  = unit

----------------------------------------------------------------------
-- Numbers

-- Unary natural numbers

data  : Set where -- Agda input mode \bn (bold nat) yields ℕ
  zero : 
  suc  :   

-- Support for natural number literals.

{-# BUILTIN NATURAL     #-}
{-# BUILTIN ZERO    zero #-}
{-# BUILTIN SUC     suc  #-}

-- Bounded natural numbers. A value of type Fin n is smaller than n.
-- Note that there are two ways of creating a number in Fin (suc n)
-- but no way to create a number in Fin zero.
data Fin :   Set where
  zero :  {n}           Fin (suc n)
  suc  :  {n}  Fin n   Fin (suc n)

-- A decision procedure for equality. If the two numbers are equal,
-- then a proof is returned (just as in Lecture 7 where it was used to
-- check equality of type codes).

infix 5 _≟-Fin_

_≟-Fin_ :  {n} (i j : Fin n)  Maybe (i  j)
zero   ≟-Fin  zero    =  just refl
suc i  ≟-Fin  suc j   =  cong suc  <$>  i ≟-Fin j  -- recursive call
_      ≟-Fin  _       =  nothing

----------------------------------------------------------------------
-- Lists and vectors

-- Finite lists.

infixr 5 _∷_

data List (A : Set) : Set where
  []  : List A
  _∷_ : A  List A  List A

-- Append.

infixr 5 _++_

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

-- Vectors. A vector of type Vec A n has length n.

data Vec (A : Set) :   Set where
  []  : Vec A zero
  _∷_ :  {n}  A  Vec A n  Vec A (suc n)

-- Safe lookup.

lookup :  {A n}  Fin n  Vec A n  A
lookup zero    (x  xs) = x
lookup (suc i) (x  xs) = lookup i xs