{-
Agda Implementors' Meeting VI
Göteborg
May 24 - 30, 2007
Hello Agda!
Ulf Norell
-}
-- Records are labeled sigma types.
module Records where
open import Nat
open import Bool
{-
A very simple record.
-}
record Point : Set where
field
x : Nat
y : Nat
-- A record can be seen as a one constructor datatype. In this case:
data Point' : Set where
mkPoint : (x : Nat)(y : Nat) -> Point'
-- There are a few differences, though:
-- To construct a record you use the syntax record { ..; x = e; .. }
origin : Point
origin = record { x = 0; y = 0 }
-- instead of
origin' : Point'
origin' = mkPoint 0 0
-- What's more interesting is that you get projection functions
-- for free when you declare a record. More precisely, you get a module
-- parameterised over a record, containing functions corresponding to the
-- fields. In the Point example you get:
{-
module Point (p : Point) where
x : Nat
y : Nat
-}
-- So Point.x : Point -> Nat is the projection function for the field x.
getX : Point -> Nat
getX = Point.x
-- A nifty thing with having the projection functions in a module is that
-- you can apply the module to a record value, in effect opening the record.
sum : Point -> Nat
sum p = x + y
where
open module Pp = Point p
-- The final difference between records and datatypes is that we have
-- η-equality on records.
data _==_ {A : Set}(x : A) : A -> Set where
refl : x == x
η-Point : (p : Point) -> p == record { x = Point.x p; y = Point.y p }
η-Point p = refl
{-
The empty record
-}
-- One interesting benefit of this is that we get a unit type with
-- η-equality.
record True : Set where
tt : True
tt = record{}
-- Now, since any element of True is equal to tt, metavariables of
-- type True will simply disappear. The following cute example exploits
-- this:
data False : Set where
NonZero : Nat -> Set
NonZero zero = False
NonZero (suc _) = True
-- We make the proof that m is non-zero implicit.
_/_ : (n m : Nat){p : NonZero m} -> Nat
(n / zero) {}
zero / suc m = zero
suc n / suc m = div (suc n) (suc m) m
where
div : Nat -> Nat -> Nat -> Nat
div zero zero c = suc zero
div zero (suc y) c = zero
div (suc x) zero c = suc (div x c c)
div (suc x) (suc y) c = div x y c
-- Now, as long as we're dividing by things which are obviously
-- NonZero we can completely ignore the proof.
five = 17 / 3
{-
A dependent record
-}
-- Of course, records can be dependent, and have parameters.
record ∃ {A : Set}(P : A -> Set) : Set where
witness : A
proof : P witness