Agda-2.3.2.2: examples/AIM6/HelloAgda/Families.agda
{-
Agda Implementors' Meeting VI
Göteborg
May 24 - 30, 2007
Hello Agda!
Ulf Norell
-}
-- Now we're getting somewhere! Inductive families of datatypes.
module Families where
-- You can import modules defined in other files.
-- More details later...
open import Naturals
-- Think of an inductive family...
module Vec where
data Vec (A : Set) : Nat -> Set where
[] : Vec A zero
_::_ : {n : Nat} -> A -> Vec A n -> Vec A (suc n)
infixr 40 _::_
-- Some simple functions
head : {A : Set}{n : Nat} -> Vec A (suc n) -> A
head (x :: _) = x -- no need for a [] case
-- Does the definition look familiar?
map : {A B : Set}{n : Nat} -> (A -> B) -> Vec A n -> Vec B n
map f [] = []
map f (x :: xs) = f x :: map f xs
infixr 40 _++_
_++_ : {A : Set}{n m : Nat} -> Vec A n -> Vec A m -> Vec A (n + m)
[] ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)
{-
Wait a second.. what's really going on here?
All the indices were conveniently implicit!
-}
-- Ok. Let's make the implicit stuff explicit.
module WhatsGoingOnHere? where
open Vec using (Vec; []; _::_)
-- Now what's this funny dot thing?
map : {A B : Set}(n : Nat) -> (A -> B) -> Vec A n -> Vec B n
map .zero f [] = []
map .(suc _) f (x :: xs) = f x :: map _ f xs
-- Basically the dot means: inside is not a pattern at all but a
-- term whose value is uniquely determined by type checking
-- the actual pattern.
-- In the cases above the types of the patterns
-- [] and (_::_ {n} x xs)
-- forces the first argument to be zero and suc n respectively.
-- So, that's what we write.
-- We could spend hours talking about this, but let's move on...
-- Let's do some other interesting families.
-- The identity type.
data _==_ {A : Set}(x : A) : A -> Set where
refl : x == x
infix 30 _==_
infix 20 ¬_
-- In the presence of families we get a lot more empty types.
data Bool : Set where
true : Bool
false : Bool
data False : Set where
¬_ : Set -> Set
¬ A = A -> False
_≠_ : {A : Set} -> A -> A -> Set
x ≠ y = ¬ x == y
true≠false : true == false -> False -- true ≠ false
true≠false ()
-- [The following example might have worked at AIM6, but it does not
-- work now, so I commented it out. /NAD]
-- lem : (n : Nat) -> n == suc n -> False
-- lem n ()
-- Why does this work: true == false is an empty type.
{-
What's next?
-}
-- Actually, inductive families are sufficiently fun that
-- you'll never get bored, but there's even more fun to be had.
-- Move on to: With.agda