123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- {-
- 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
|