Records.agda 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. {-
  2. Agda Implementors' Meeting VI
  3. Göteborg
  4. May 24 - 30, 2007
  5. Hello Agda!
  6. Ulf Norell
  7. -}
  8. -- Records are labeled sigma types.
  9. module Records where
  10. open import Nat
  11. open import Bool
  12. {-
  13. A very simple record.
  14. -}
  15. record Point : Set where
  16. field
  17. x : Nat
  18. y : Nat
  19. -- A record can be seen as a one constructor datatype. In this case:
  20. data Point' : Set where
  21. mkPoint : (x : Nat)(y : Nat) -> Point'
  22. -- There are a few differences, though:
  23. -- To construct a record you use the syntax record { ..; x = e; .. }
  24. origin : Point
  25. origin = record { x = 0; y = 0 }
  26. -- instead of
  27. origin' : Point'
  28. origin' = mkPoint 0 0
  29. -- What's more interesting is that you get projection functions
  30. -- for free when you declare a record. More precisely, you get a module
  31. -- parameterised over a record, containing functions corresponding to the
  32. -- fields. In the Point example you get:
  33. {-
  34. module Point (p : Point) where
  35. x : Nat
  36. y : Nat
  37. -}
  38. -- So Point.x : Point -> Nat is the projection function for the field x.
  39. getX : Point -> Nat
  40. getX = Point.x
  41. -- A nifty thing with having the projection functions in a module is that
  42. -- you can apply the module to a record value, in effect opening the record.
  43. sum : Point -> Nat
  44. sum p = x + y
  45. where
  46. open module Pp = Point p
  47. -- The final difference between records and datatypes is that we have
  48. -- η-equality on records.
  49. data _==_ {A : Set}(x : A) : A -> Set where
  50. refl : x == x
  51. η-Point : (p : Point) -> p == record { x = Point.x p; y = Point.y p }
  52. η-Point p = refl
  53. {-
  54. The empty record
  55. -}
  56. -- One interesting benefit of this is that we get a unit type with
  57. -- η-equality.
  58. record True : Set where
  59. tt : True
  60. tt = record{}
  61. -- Now, since any element of True is equal to tt, metavariables of
  62. -- type True will simply disappear. The following cute example exploits
  63. -- this:
  64. data False : Set where
  65. NonZero : Nat -> Set
  66. NonZero zero = False
  67. NonZero (suc _) = True
  68. -- We make the proof that m is non-zero implicit.
  69. _/_ : (n m : Nat){p : NonZero m} -> Nat
  70. (n / zero) {}
  71. zero / suc m = zero
  72. suc n / suc m = div (suc n) (suc m) m
  73. where
  74. div : Nat -> Nat -> Nat -> Nat
  75. div zero zero c = suc zero
  76. div zero (suc y) c = zero
  77. div (suc x) zero c = suc (div x c c)
  78. div (suc x) (suc y) c = div x y c
  79. -- Now, as long as we're dividing by things which are obviously
  80. -- NonZero we can completely ignore the proof.
  81. five = 17 / 3
  82. {-
  83. A dependent record
  84. -}
  85. -- Of course, records can be dependent, and have parameters.
  86. record ∃ {A : Set}(P : A -> Set) : Set where
  87. witness : A
  88. proof : P witness