------------------------------------------------------------------------------
-- Dependently typed functional languages - 2011-01

-- Inductive families (datatype families, inductively defined family of sets)
------------------------------------------------------------------------------

-- References:

-- [1] Ana Bove and Peter Dybjer. Dependent types at work. In Ana Bove
--     et al., editors. LerNet ALFA Summer School 2008, volume 5520 of
--     LNCS, 2009. pp. 57-99.

-- [2] Ulf Norell. Dependently typed programming in Agda. In Koopman
--     et al., editors. Advanced Functional Programming 6th
--     International School, AFP 2008, volume 5832 of
--     LNCS. Springer-Verlag, 2009. pp. 230-266.

{-# OPTIONS --exact-split    #-}
{-# OPTIONS --guardedness    #-}
{-# OPTIONS --no-sized-types #-}
{-# OPTIONS --safe           #-}
{-# OPTIONS --warning=all    #-}
{-# OPTIONS --warning=error  #-}
{-# OPTIONS --without-K      #-}

module Lecture.InductiveFamilies where

open import Data.Nat renaming (suc to succ)

open import Extra.Data.Unit
open import Extra.Data.Product

------------------------------------------------------------------------------

-- Motivation: Problems in the definition of some Haskell functions
-- (from Data.List (GHC 7.0.3))

-- | Extract the first element of a list, which must be non-empty.
-- head                    :: [a] -> a
-- head (x:_)              =  x
-- head []                 =  badHead

-- | Extract the elements after the head of a list, which must be non-empty.
-- tail                    :: [a] -> [a]
-- tail (_:xs)             =  xs
-- tail []                 =  errorEmptyList "tail"

-- | 'zip' takes two lists and returns a list of corresponding pairs.
-- If one input list is short, excess elements of the longer list are
-- discarded.
-- zip :: [a] -> [b] -> [(a,b)]
-- zip (a:as) (b:bs) = (a,b) : zip as bs
-- zip _      _      = []

------------------------------------------------------------------------------
-- Vectors: Types of lists of a certain length

-- Inductive family definition:

infixr 5 _∷_

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

-- The type of vectors.
-- Vec A : ℕ → Set, i.e. Vec A is an inductive family parametrized by
-- A and indexed by the natural numbers.

-- The data constructors:
-- [] : It generates a vector of length 0.

-- _∷_ : It generates a vector of length (n + 1) from a vector of
--       length n and an element of A.

-- Parameters: They remain the same throughout the definition.

-- Indexes: They vary in types of the data constructors.

-- Examples

-- Using the inductive familiy of vectors we can express the type of
-- non-empty lists.

head : {A : Set}{n : }  Vec A (succ n)  A
head (x  xs) = x

tail : {A : Set}{n : }  Vec A (succ n)  Vec A n
tail (x  xs) = xs

-- Using the inductive familiy of vectors we can express that two list
-- are the same length.
zip : {A B : Set}(n : )  Vec A n  Vec B n  Vec (A × B) n
zip .zero      []            []       = []
zip .(succ n) (_∷_ {n} x xs) (y  ys) = (x , y)  zip n xs ys

------------------------------------------------------------------------------
-- Alternative definition of vectors: Recursive definition by
-- induction on the length

-- Mathematical definition
-- A⁰      = 1
-- A^(n+1) = A x A^n

VecR : Set    Set
VecR A zero     = 
VecR A (succ n) = A × (VecR A n)

-- Examples

-- Using the recursive definition of vectors we can express the type
-- of non-empty lists.
headR : {A : Set}{n : }  VecR A (succ n)  A
headR (x , xs) = x

-- Using the recursive definition of vectors we can express that two
-- list are the same length.
zipR : {A B : Set}(n : )  VecR A n  VecR B n  VecR (A × B) n
zipR zero     xs       ys       = _
zipR (succ n) (x , xs) (y , ys) = (x , y) , (zipR n xs ys)

------------------------------------------------------------------------------
-- Inductive families or recursive definitions?

-- "In the remainder of the notes we will, however, mostly use
-- inductive families. This should not be taken as a statement that
-- inductive families are always more convenient than recursive
-- ones. When both methods are applicable, one needs to carefully
-- consider how they will be used before choosing the one or the
-- other". [1, p. 70]