Modules.agda 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. -- This module gives an introduction to the module system of Agda.
  2. module Introduction.Modules where
  3. ---------------------------------------------------------------------------
  4. -- Simple sub-modules
  5. ---------------------------------------------------------------------------
  6. -- As mentioned in 'Introduction.Basics' each file contains a single top-level
  7. -- module. This module can contain any number of sub-modules. A sub-module is
  8. -- declared in the same way as the top-level module, except that its name is
  9. -- not qualified.
  10. module Numbers where
  11. -- The contents of the top-level module do not have to be indented, but the
  12. -- contents of a sub-module do.
  13. data Nat : Set where
  14. zero : Nat
  15. suc : Nat -> Nat
  16. -- Outside a module its contents can be accessed using the name of the module.
  17. one : Numbers.Nat
  18. one = Numbers.suc Numbers.zero
  19. -- Of course, this would get very tedious after a while, so to bring the
  20. -- contents of a module into scope you can use an 'open' declaration.
  21. open Numbers
  22. two : Nat
  23. two = suc one
  24. -- When opening a module it is possible to control what names are brought into
  25. -- scope. The open declaration supports three modifiers :
  26. -- using (x1; ..; xn) only bring x1 .. xn into scope
  27. -- renaming (x to y;..) bring y into scope and make it refer to the name x
  28. -- from the opened module.
  29. -- hiding (x1; ..; xn) bring everything except x1 .. xn into scope
  30. -- The using and hiding modifiers can be combined with renaming but not with
  31. -- each other.
  32. -- For example, this will bring the names z and s (and nothing else) into
  33. -- scope as new names for zero and suc.
  34. open Numbers using () renaming (zero to z; suc to s)
  35. -- We can now pattern match on the renamed constructors.
  36. plus : Nat -> Nat -> Nat
  37. plus z m = m
  38. plus (s n) m = s (plus n m)
  39. ---------------------------------------------------------------------------
  40. -- 'private' and 'abstract'
  41. ---------------------------------------------------------------------------
  42. -- Above we saw how to control which names are brought into scope when opening
  43. -- a module. It is also possible to restrict what is visible outside a module
  44. -- by declaring things 'private'. Declaring something private will only prevent
  45. -- someone from using it outside the module, it doesn't prevent it from showing
  46. -- up after reduction, or from it to reduce.
  47. -- To prevent something from reducing (effectively hiding the definition) it
  48. -- can be declared 'abstract'.
  49. module Datastructures where
  50. private
  51. data List (A : Set) : Set where
  52. nil : List A
  53. _::_ : A -> List A -> List A
  54. _++_ : {A : Set} -> List A -> List A -> List A
  55. nil ++ ys = ys
  56. (x :: xs) ++ ys = x :: (xs ++ ys)
  57. reverse : {A : Set} -> List A -> List A
  58. reverse nil = nil
  59. reverse (x :: xs) = reverse xs ++ (x :: nil)
  60. -- Not making the stack operations abstract will reveal the underlying
  61. -- implementation, even though it's private.
  62. Stack : Set -> Set
  63. Stack A = List A
  64. emptyS : {A : Set} -> Stack A
  65. emptyS = nil
  66. push : {A : Set} -> A -> Stack A -> Stack A
  67. push x xs = x :: xs
  68. abstract
  69. -- An abstract datatype doesn't reveal its constructors
  70. data Queue (A : Set) : Set where
  71. queue : (front back : List A) -> Queue A -- invariant : if the front is
  72. -- empty, so is the back
  73. -- Abstraction is contagious, anything that pattern matches on a queue must
  74. -- also be abstract.
  75. private
  76. -- make sure the invariant is preserved
  77. flip : {A : Set} -> Queue A -> Queue A
  78. flip (queue nil back) = queue (reverse back) nil
  79. flip q = q
  80. -- these functions will not reduce outside the module
  81. emptyQ : {A : Set} -> Queue A
  82. emptyQ = queue nil nil
  83. enqueue : {A : Set} -> A -> Queue A -> Queue A
  84. enqueue x (queue front back) = flip (queue front (x :: back))
  85. open Datastructures
  86. testS = push zero emptyS
  87. testQ = enqueue zero emptyQ