2
{- An agda file contains a single module. The module name should correspond to
3
the name and path of the file. The path is relative to the project root. In
4
this case the project root is the root of Agda II. Modules can be
5
parameterised, but in this case we choose not to parameterise the top-level
9
module examples.syntax.Syntax where
11
-- It is recommended that the body of the top-level module is indented by a
12
-- small amount, but this is not enforced in the syntax.
14
-- You can have modules inside modules. The name of a sub-module isn't
16
module Expressions (X : Set)(x1, x2 : X) where
18
-- There are three forms of sorts. Set = Set0.
23
-- Independent function space.
27
-- Implicit independent function space. This is mostly included for
28
-- symmetry, I can't come up with an example when this would be useful.
32
-- Dependent function space.
33
fun3 : (A:Set) -> A -> A
36
-- Implicit dependent function space. 'A' is implicit so we don't have to
37
-- write it out in the function definition.
38
fun4 : {A:Set} -> A -> A
41
-- You can also write independent functions using the dependent function
42
-- space syntax. Not that you'd ever want to.
46
-- Lambdas can be domain free.
47
const1 : {A, B : Set} -> A -> B -> A
50
-- Or completely typed.
51
const2 = \{A:Set}{B:Set}(x:A)(y:B) -> x -- inferable, no type needed
53
-- You cannot mix typed and untyped arguments in the same lambda.
54
const3 : {A, B : Set} -> A -> B -> A
55
const3 = \{A}{B} -> \(x:A)(y:B) -> x
57
-- You can have wildcards in lambdas
58
const4 : {A, B : Set} -> A -> B -> A
61
-- Implicit arguments can be omitted in applications.
65
x' = const1 {X} {X} x1 x2
67
-- Infix operators can be bound by lambdas. See ComplexDeclarations for
68
-- more information about infix operators.
69
dup : {A:Set} -> (A -> A -> A) -> A -> A
72
-- The two basic declarations are function definitions and datatype
74
module BasicDeclarations (X : Set) where
76
-- The most common declaration is the function definition. It consists of
77
-- two parts; a type signature and a set of function clauses. Type
78
-- signatures have the form 'id : type', no telescopes are allowed at this
79
-- point. This can be discussed.
83
-- You can omit the type signature if the type can be inferred.
86
-- Datatypes are introduced with the data keyword.
91
-- The parameters to the datatype (A in this case) are in scope in the
92
-- types of the constructors. At the moment inductive families are not
94
data List (A : Set) : Set where
96
(::) : A -> List A -> List A
98
-- When using a constructor as a function, the parameters are hidden
100
singleton : X -> List X
101
singleton x = x :: nil
103
singleton' : X -> List X
104
singleton' x = (::) {X} x (nil {X})
106
-- You can pattern match over elements of a datatype when defining
107
-- functions (and only then).
108
null : (A : Set) -> List A -> Bool
110
null A (x::xs) = false
112
-- Patterns can be nested (and functions can be recursive).
113
and : List Bool -> Bool
115
and (true::xs) = and xs
116
and (false::xs) = false
118
-- Functions can be defined in an infix style. When doing this it must be
119
-- clear what name is being defined without looking at fixities. Hence we
120
-- could never remove the parenthesis around x::xs in the second clause.
121
(++) : List X -> List X -> List X
123
(x::xs) ++ ys = x :: (xs ++ ys)
125
-- You can also use a combination of infix and prefix.
126
(@) : {A, B, C : Set} -> (B -> C) -> (A -> B) -> A -> C
129
-- Declarations can appear in many different contexts and not all
130
-- declarations are allowed everywhere.
131
module ComplexDeclarations (X : Set) where
133
-- You can introduce new constants with the postulate declaration. A
134
-- postulate declaration takes a list of type signatures.
138
-- Let's introduce some datatypes so we have something to work with. At the
139
-- same time we illustrate that layout is optional.
140
data Nat : Set where { zero : Nat; suc : Nat -> Nat }
141
data Bool : Set where { false : Bool; true : Bool }
143
{- We can declare the fixity of infix symbols. The fixity is tied to a
144
particular binding of a name. The binding doesn't have to be in scope
145
directly (as in the example below), but it should be possible to bring
146
it into scope by moving the fixity declaration further down in the
147
current block (but never inside things).
149
The following wouldn't be allowed:
153
(+) : Nat -> Nat -> Nat
156
There are three forms: infix, infixl and infixr, for non-associative,
157
left associative and right associative respectively. The number is the
163
(+) : Nat -> Nat -> Nat
165
n + suc m = suc (n + m)
169
-- The following code is to stress test the handling of infix applications.
176
(@) : Nat -> Nat -> Nat
177
(#) : Nat -> Nat -> Nat
178
(@@) : Nat -> Nat -> Nat
179
(##) : Nat -> Nat -> Nat
187
test5 = z ## z # z ## z # z
188
test6 = z @@ z @ z @@ z @ z
189
test7 = z # z @@ z @@ z # z
191
-- Mutually recursive definition are introduced using the 'mutual' keyword.
192
-- A mutual block can contain function definitions, datatypes
193
-- (induction-recursion) and fixity declarations.
203
-- If a function is declared abstract the definition of the function is not
204
-- visible outside the module. For an abstract datatype the constructors
205
-- are hidden. Definitions that can appear in an abstract block are:
206
-- function definitions, data declarations, fixity declarations, mutual
207
-- blocks, open and name space declarations (see NameSpaces).
209
data Stack : Set where
211
cons : A -> Stack -> Stack
216
push : A -> Stack -> Stack
219
-- Local declarations are introduces either with a let or in a where
220
-- clause. A where clause is attached to a function clause. Everything that
221
-- can appear in an abstract block can appear in a local declaration, plus
222
-- abstract blocks. Local functions can be recursive.
223
foo : (A : Set) -> A -> A
224
foo A x = let f : Local -> A
228
data Local : Set where
231
-- You can declare things to be private to the current module. This means
232
-- that they cannot be accessed outside the module (but they're still
233
-- visible inside the module and its submodules). The only things that
234
-- cannot appear in a private block are other private blocks and import
240
-- Private declarations can go inside mutual and abstract blocks.
242
private f : Nat -> Nat
253
private h : Nat' -> Nat
257
-- A name space is something that contains names. You can create new
258
-- name spaces and bring names from a name space into scope.
259
module NameSpaces where
261
-- To access definitions from a module in a different file, you have to
262
-- 'import' this module. Only top-level modules (which have their own
263
-- files) can be imported.
265
-- If the imported module is not parameterised a name space with the same
266
-- name as the module is created.
267
import examples.syntax.ModuleA
269
-- We can now refer to things from ModuleA using the created name
270
-- space. Note that no unqualified names were brought into scope
271
-- (except, perhaps, the name of the name space). [To bring
272
-- unqualified names into scope we have to use the 'open'
274
FunnyNat = examples.syntax.ModuleA.Nat
276
-- If the name of an imported module clashes with a local module we might
277
-- have to rename the module we are importing
278
import examples.syntax.ModuleA as A
279
import examples.syntax.ModuleA as A' using (Nat)
284
{- You can't project from a parameterised module. It has to be
285
instantiated first. The only thing that happens when importing
286
is that the module name 'examples.syntax.ModuleB' is brought
287
into scope (and the type checker goes away and type checks this
290
import examples.syntax.ModuleB
292
-- To instantiate ModuleB we need something to instantiate it with.
294
(==) : X -> X -> Prop
295
refl : (x : X) -> x == x
297
-- To instantiate a module you create a new module and define it as the
298
-- instantiation in question.
299
module B = examples.syntax.ModuleB X (==) refl
301
-- Now the module B contains all the names from ModuleB.
303
And = B./\ -- qualified operators are not infix symbols
305
dummyX = B.SubModule.dummy -- submodules of ModuleB are also in scope
307
-- This of course works for non-parameterised modules as well.
310
-- And you can create parameterised modules this way.
311
module BX ((==) : X -> X -> Prop)(refl : (x : X) -> x == x) = B X (==) refl
313
-- To bring names from a module into scope you use an open declaration.
314
open examples.syntax.ModuleA
317
two = eval (plus (suc zero) (suc zero))
319
{- In all three declarations (import, module instantiation and open) you
320
can give modifiers that affect the names which are imported. There are
323
using (x1;..;xn) only import x1,..,xn
324
hiding (x1;..;xn) import everything but x1,..,xn
325
renaming (x1 to y1;..;xn to yn) import x1,..,xn but call them y1,..,yn
328
- a modifier can appear only once
329
- 'using' and 'hiding' cannot appear together
330
- imported names must be distinct (e.g. you cannot rename to a name
331
that is already being imported).
334
-- B1 only contains True and False
335
module B1 = B using (True; False)
337
-- B2 contains True, False and And where And = B./\
338
module B2 = B using (True; False) renaming (/\ to And)
340
-- B3 contains everything from B except reflEqList and eqList, plus ===
341
-- where (===) = B.eqList.
342
module B3 = B hiding (reflEqList) renaming (eqList to ===)
344
-- When referring to sub modules you have to be explicitly about it being
346
module B4 = B renaming (module SubModule to Sub)
351
-- There are two kinds of meta variables; question marks and underscores.
352
-- Question marks are used for interaction and underscores for implicit
354
module MetaVariables where
359
-- There are two ways of writing a question mark: ? and {! ... !}
360
-- The type checker will not complain about unsolved question marks (unless
361
-- you claim you are done).
362
incomplete : {A:Set} -> A -> A
365
incomplete' : {A:Set} -> A -> A
366
incomplete' x = {! you can put anything in here,
367
even {! nested holes !}
370
-- Underscores should always be solvable locally. Internally underscores
371
-- are inserted for implicit arguments, but there are cases where you would
372
-- like to write them explicitly. For instance, if you want to give one but
373
-- not all implicit arguments to a function explicitly.
374
underscore : ({A,B,C:Set} -> (A -> A) -> B -> C) -> X
375
underscore f = f {_} {X} {_} (\y -> y) x
377
-- Note that '_' is not an identifier character. The current use of
378
-- underscore is not the real reason for this. The idea is rather that
379
-- underscore will be used for subscripts.
380
id : (A : Set) -> A -> A
383
x' = id_x -- this means id _ x
385
-- The parser supports four types of literals. The syntax is the same as in
386
-- Haskell (since that meant I could steal the lexer for them from ghc).
387
module Literals where
389
-- We haven't decided how to handle built-in types.
390
postulate Integer : Set
399
helloWorld = "Hello World!"
407
-- There are few things that the parser doesn't implement.
409
{- Fancy case. I haven't been able to come up with a nice syntax for the
410
fancy case statement. The difficulty is that we should make it clear
411
what arguments to the elimination rule will appear as patterns (the
412
targets). Suggestions are welcome.
414
Also I'm not sure that we want the fancy case. It would be better to
415
have a good way of doing actual pattern matching on inductive families.
418
{- Relative imports. You might want to be able to say
422
to import the module 'current.directory.ModuleA'. Easy to implement but
423
I'm not sure it's that painful to write the complete name (not a problem
424
in Haskell for instance). Drawbacks: it looks kind of funny and it adds
425
an extra bit of syntax to remember.