strong_0
26.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
/**************************************************************************************
_____ ___. .__ ________
/ _ \ ____ __ _\_ |__ |__| ______ \_____ \
/ /_\ \ / \| | \ __ \| |/ ___/ / ____/
/ | \ | \ | / \_\ \ |\___ \ / \
\____|__ /___| /____/|___ /__/____ > \_______ \
\/ The \/ Anubis \/ 2 \/ Project \/
Name of this file: strong_0 (text file)
Purpose of this file: Description of ``strong'' types and terms.
Authors (Name [initials]): Alain Proute' [AP]
Updates ([initials] (date) comment):
[AP] (2007 jun 08) Creation of this file.
**************************************************************************************/
``Strong'' types and terms are the result of interpreting ``weak'' expressions.
*** Strong contexts and De Bruijn symbols.
A strong context is just a list of strong types. In strong items (types and terms)
there are no local symbols. Instead, there are ``De Bruijn'' symbols refering to a
depth into the context. Here is how it works. Normally, a context is a list of pairs:
[(x_0,T_0),...,(x_k,T_k)]
and the type of the symbol 'x' is 'T_i' if 'x_i' is the leftmost occurrence of 'x' in
the heads of the above list.
The corresponding strong context is just the list:
[T_0,...,T_k]
and a symbol, instead of having a name, has just a ``depth''. Such symbols (also called
``De Bruijn'' symbols) will be denoted 's(i)', where 'i' is the depth indication. So,
relative to the above strong context, 's(i)' has type 'T_i' (for all 'i', such that '0
=< i =< k').
From the stack machine viewpoint, a strong context is just the description of the
stack. It indicates what types of data are stacked. Hence, 's(i)' is just an
instruction saying: 'get the datum at depth i in the stack'.
Notice that this does not imply that all stack slots have the same size. If each type
has a well defined size (number of bits or bytes needed for any datum of this type),
the depths may be computed from these sizes.
*** Shifting.
If a strong term 't' is meaningful in a strong context 'G', it is no more meaningful in
'[U . G]', but its ``shifting'' is (and represents the same thing in the new
context). The result of shifting 't' 'n' times is denoted 't[n]'.
Shifting is very easy to understand from a stack machine view point. Indeed, consider a
strong term 't' meaningful in some strong context 'G' as a program executable using the
stack 'G'. If 'n' items are pushed on top of the stack, the program 't' must be
modified so as to be still executable with this new stack. Clearly, the only thing to
do is to add 'n' to the depths of all free occurrences of De Bruijn symbols. This
operation is called ``shifting by n''.
We will also have to shift strong types, since they may also depend on symbols, and
since terms refer to types. Conversely, shifting of strong types requires shifting of
strong terms, because of witness types. Hence, the two shifting algorithms are cross
recursive.
*** Replacement.
We will also have to replace a De Bruijn symbol by a strong term within either a strong
term or a strong type. The result of replacing the symbol 's(i)' by the term 'a' in 't'
is denoted: t[a/i]. How it works is defined in details below in this file.
*** Rules for constructing correct strong contexts, types and terms.
Strong items (contexts, types and terms) are defined using three sorts of ``jugments'',
which are the following:
/G meaning that G is a strong context
T/G meaning that T is a strong type in (relative to) the (strong) context G
t:T/G meaning that t is a strong term of (strong) type T in the (strong) context G
A ``rule'' for defining a strong item is presented as follows:
J_1 ... J_k
-----------
J
where J_1,...,J_k are the ``premises'' or ``conditions'' and J is the ``conclusion'' of
the rule. The meaning of the rule is that J is true as soon as J_1,...,J_k are all
true.
However, the meaning of these judgements also depend on:
- The global context.
- A list of parameters.
- An environment.
We will not represent them explicitely in our rules.
Each definition in the global context is supposed to be correct. Hence, each one has a
meaning, and this meaning is a strong item (strong type for a type definition, strong
term for a datum definition).
We may also have a list of parameters. Each one is supposed to represent an arbitrary
correct type. This is the case when we are currently checking a schema.
We may also have unknowns. Recall that an environment is a list of pairs:
[(X_1,T_1),...,(X_k,T_k)]
where each 'X_i' is an unknown, and each 'T_i' a strong type (there is also a non
circularity condition). In the presence of this environment, the unknown 'X_i'
represents the type 'T_i'. Notice that 'T_i' may still contain other unknowns. Of
course, any strong type or strong term containing an unknown is ambiguous (this is
called ``parametric ambiguity'').
*** Rules for contexts.
- The empty context. [] is a strong context.
---
/[]
- Enlargement of contexts. If T is a type relative to the context G, then [T . G] is a
strong context.
T/G
--------
/[T . G]
*** Rules for types.
- Strong parameter. It represents a valid arbitrary type if and only if it is a member
of the given list of parameters.
- Strong unknown. Each unknown represents a type to be determined. Of course, if it has
a value relative to the current environment, it represents this value.
- Strong defined types. They are made of a type id, and a list of strong types, each
one corresponding to a parameter of the type having this id.
- Strong product types:
T_1/G, ..., T_k/G
------------------------
_Prod(T_1,...,T_k)/G
- Strong functional types: Notice that 'U' is a type relative to '[T . G]', not to 'G'.
This means that 'U' may depend on 'T'. Hence, strong functional types are dependant.
T/G, U/[T . G]
------------------ '_Functional(T,U)' is also denoted 'T -> U'
_Functional(T,U)/G
- Strong Omega: '_Omega' is a type in all circumstances.
/G
---------
_Omega/G
- Strong witness types: To each strong statement is associated a strong witness type.
E:_Omega/G
---------------------
_Witness(E)/G
- Strong (universally) quantified types (Girard's system F types): If T is a strong
type, and $X a parameter, then '_Quantified($X T)' is a strong type (with no free
occurrence of the parameter $X).
T/G
-------------------
_Quantified($X T)/G
public type StrongTerm:...
public type StrongType:
_Parameter (String name),
_Defined (Int32 type_id,
List(StrongType) operands),
_Product (List(StrongType)),
_Functional (StrongType source,
StrongType target),
_Omega,
_Witness (StrongTerm statement),
_Quantified (String parameter,
StrongType).
*** Rules for terms.
- De Bruijn symbols: 's(i)' represents the datum at depth 'i' in the context. The head
of the context (top of stack) has depth '0'.
--------------
s(0):T/[T . G]
s(i):T/G, U/G
----------------
s(i+1):T/[U . G]
- Strong tuples: A strong tuple has the form 'tuple(t_1,...,t_k)', where
't_1',...,'t_k' are strong terms. If the type of 't_i' relative to the strong context
'G' is 'T_i', then the type of 'tuple(t_1,...,t_k)' relative to 'G' is
'_Prod(T_1,...,T_k)'.
- t_1:T_1/G,...,t_k:T_k/G
---------------------------------------
tuple(t_1,...,t_k):_Prod(T_1,...,T_k)/G
- Strong projections: It 't' is a strong term of type '_Prod(T_1,...,T_k)', and if 'i'
is such that '1 =< i =< k', then 'proj(i,t)' is a strong term of type 'T_i'.
t:_Prod(T_1,...,T_k)/G
---------------------- for any i such that 1 =< i =< k
proj(i,t):T_i/G
- Strong inclusions: Inclusions are the constructors for sum types, i.e. they
correspond to alternatives in weak types. Each alternative has a type (which is a
product type when the re are several components).
If 't' is a term of type 'T_i', and if 'T_i' is the type of alternative number 'i' of
some type 'U', i.e. if U = T_1 + ... + T_k, then 'incl(U,i,t)' is a strong term of type
'U'.
- Strong conditionals: Conditionals are the destructors for sum types. If 'T' is a
strong defined type whose types of alternatives are 'U_1',...,'U_k', if 't' is a strong
term of type 'T', if 'V' is a strong type, and if 'c_1',...,'c_k' are strong terms of
respective types 'U_1 -> V',...,'U_k -> V', then 'cond(T,t,c_1,...,c_k)' is a strong
term of type 'V'.
t:T/G, c_1:U_1 -> V,...,c_k:U_k -> V
------------------------------------
cond(T,t,c_1,...,c_k):V/G
- Strong functions: If 'T' is a strong type relative to strong context 'G', if 'E' is a
strong term of type 'U' relative to '[T . G]', then 'lambda(T,E)' is a strong term of
strong type 'T -> U' relative to 'G'.
E:U/[T . G]
----------------------
lambda(T,E):(T -> U)/G
- Strong applicative terms: If 'f' is a strong term of type 'T -> U' in the strong
context 'G', and if 'a' is a strong term of type 'T' in the context 'G', 'app(f,a)' is
a strong term of type 'U[a/0]' in the context 'G'.
f:(T -> U)/G, a:T/G
-------------------
app(f,a):U[a/0]/G
- Strong universally quantified statements: If 'T' is a strong type in the strong
context 'G', if 'E' is a strong term of type '_Omega' in the context '[T . G]', then
'forall(T,E)' is a strong term of type '_Omega' in the context 'G'.
E:_Omega/[T . G]
--------------------
forall(T,E):_Omega/G
In order to declare the three next sorts of strong terms, we need the 'macros' 'exists'
and 'exists_unique'. They have the same syntax as 'forall'. They will be defined later
below.
- strong description terms: If 'p' is a strong term of type
'_Witness(exists_unique(T,E))', then 'description(p)' is strong term of type 'T'.
p:_Witness(exists_unique(T,E))/G
--------------------------------
description(p):T/G
- Strong property terms: If 'p' is a strong term of type
'_Witness(exists_unique(T,E))', then 'property(p)' is strong term of type
'_Witness(E[description(p)/0])'.
p:_Witness(exists_unique(T,E))/G
-------------------------------------------
property(p):_Witness(E[description(p)/0])/G
- Strong choice terms: If 'p' is a term of type '_Witness(forall(T,exists(U,E)))' then
'choice(p)' is a strong term of type:
_Witness(exists(_Functional(T,U),forall(T,E[app(s(1),s(0))/0])))
p:_Witness(forall(T,exists(U,E)))/G
----------------------------------------------------------------------------
choice(p):_Witness(exists(_Functional(T,U),forall(T,E[app(s(1),s(0))/0])))/G
- Strong parametric terms:
t:T/G
------------------------------------- $X any parameter
parametric($X t):s_Quantified($X T)/G
- Strong parametric applicative terms:
t:_Quantified($X T)/G, U/G
-----------------------------
parametric_app(t,U):T[U/$X]/G
public type StrongTerm:
global (Int32 id),
symbol (Int32 depth), // Nicolaas Govert de Bruijn symbols
tuple (List(StrongTerm)),
proj (Int32, StrongTerm),
incl (StrongType, Int32, StrongTerm),
cond (StrongType, StrongTerm test, List(StrongTerm) cases),
lambda (StrongType, StrongTerm),
app (StrongTerm f, StrongTerm a),
forall (StrongType, StrongTerm),
description (StrongTerm),
property (StrongTerm),
choice (StrongTerm),
parametric (String parameter, StrongTerm),
parametric_app (StrongTerm, StrongType).
*** The definition of shifting and replacement.
Since we now know precisely what strong types and terms are, we can define shifting and
replacement.
_Defined(N,T_1,...,T_k)[n] is _Defined(N,T_1[n],...,T_k[n])
_Product(T_1,...,T_k)[n] is _Product(T_1[n],...,T_k[n])
_Functional(T,U)[n] is _Functional(T[n],U[n])
_Omega[n] is _Omega
_Witness(E)[n] is _Witness(E[n])
_Quantified($X,T)[n] is _Quantified($X,T[n])
public define StrongType
shift
(
StrongType t,
Int32 n
).
Shifting of strong terms sometimes (lambda and forall) requires replacement.
symbol(i)[n] is symbol(i+n)
tuple(t_1,...,t_k)[n] is tuple(t_1[n],...,t_k[n])
proj(i,t)[n] is proj(i,t[n])
incl(T,i,t)[n] is incl(T[n],i,t[n])
cond(T,t,c_1,...,c_k)[n] is cond(T[n],t[n],c_1[n],...,c_k[n])
lambda(T,t)[n] is lambda(T[n],t[n][symbol(0)/n])
app(f,a)[n] is app(f[n],a[n])
forall(T,t)[n] is forall(T[n],t[n][symbol(0)/n])
description(t)[n] is description(t[n])
property(t)[n] is property(t[n])
choice(t)[n] is choice(t[n])
parametric(p,t)[n] is parametric(p,t[n])
parametric_app(t,T)[n] is parametric_app(t[n],T[n])
public define StrongTerm
shift
(
StrongTerm t,
Int32 n
).
_Defined(N,T_1,...,T_k)[a/i] is _Defined(N,T_1[a/i],...,T_k[a/i])
_Product(T_1,...,T_k)[a/i] is _Product(T_1[a/i],...,T_k[a/i])
_Functional(T,U)[a/i] is _Functional(T[a/i],U[a/i+1])
_Omega[a/i] is _Omega
_Witness(E)[a/i] is _Witness(E[a/i])
_Quantified($X T)[a/i] is _Quantified($X T[a/i])
public define StrongType // returns t[a/i]
replace
(
StrongType t,
StrongTerm a,
Int32 i
).
symbol(i)[a/i] is a
symbol(i)[a/j] is symbol(i) (if i != j)
tuple(t_1,...,t_k)[a/i] is tuple(t_1[a/i],...,t_k[a/i])
proj(n,t)[a/i] is proj(n,t[a/i])
incl(U,n,t)[a/i] is incl(U[a/i],n,t[a/i])
cond(T,t,c_1,...,c_k)[a/i] is cond(T[a/i],t[a/i],c_1[a/i],...,c_k[a/i])
lambda(T,E)[a/i] is lambda(T[a/i],E[a/i+1])
app(f,b)[a/i] is app(f[a/i],b[a/i])
forall(T,E)[a/i] is forall(T[a/i],E[a/i+1])
description(p)[a/i] is description(p[a/i])
property(p)[a/i] is property(p[a/i])
choice(p)[a/i] is choice(p[a/i])
parametric($X,t)[a/i] is parametric($X,t[a/i])
parametric_app(t,T)[a/i] is parametric_app(t[a/i],T[a/i])
public define StrongTerm // returns t[a/i]
replace
(
StrongTerm t,
StrongTerm a,
Int32 i
).
*** The meaning of witness types.
As you may see, there is no constructor for witness types. They are not needed because
the witness type '_Witness(forall(T,E))' is equal (say ``by definition'') to the type
'T -> _Witness(E)'. This is actually part of the BHK interpretation.
Also remark that 'forall' is the only constructor of type '_Omega'. Since 'forall(T,E)'
requires an operand 'E' of type '_Omega', it seems that it is impossible to construct
any term of type '_Omega'. Actually, this is not true, and we may first define the
statement 'false' as follows:
false := forall(_Omega,s(0))
Notice that 's(0)' is indeed of type '_Omega', since according to the rule defining
'forall', 's(0)' is to be interpreted relative to the context '[_Omega . G]'.
The above statement means 'false', because assuming a witness for 'false', we can prove
any statement. Indeed, assume that 'p:_Witness(false)/G', and 'E:_Omega/G', then we
have successively:
p:_Witness(forall(_Omega,s(0)))
p:_Omega -> _Witness(s(0))
app(p,E):_Witness(s(0)[E/0])
app(p,E):_Witness(E)
Next, we may define the (non dependant) implication, as follows:
E:_Omega/G, F:_Omega/G
-------------------------------------------------
implies(E,F) := forall(_Witness(E),F[1]):_Omega/G
Notice that 'F' must be shifted, in order to take into account the fact that a witness
of 'E' has been pushed on top of the stack. This is again conformal to the BHK
interpretation (precisely, the fact that a proof of 'E => F' is an algorithm producing
a proof of 'F' from a proof of 'E').
This enables to define the statement 'true' as 'false => false':
true := implies(false,false):_Omega/G
It is interesting to check that we are able to prove 'true', i.e. to find a term of
type '_Witness(true)'. Here it is:
lambda(_Witness(false),s(0))
as you may easily verify.
The next logical connector to be defined is the existential quantifier ('exists'). This
is done as follows. First of all in the user's Anubis language:
!x:T E := ?q:Omega ((?x:T (E => q)) => q)
That this is the right definition of 'exists' is well known, and is just a constructive
version of the classical rule: !x:T E := ~(?x:T ~E), where ~ is the negation.
As a strong term, this gives the following:
exists(T,E) :=
forall(_Omega,(implies(forall(T,implies(replace(shift(E,2),s(0),2),s(2))),s(1))))
i.e. in less formal language:
!T E := ?Omega ((?T (E[2][s(0)/2] => s(2))) => s(1))
Next, we define the (non dependant) conjunction of 'E' and 'F':
and(E,F) := exists(_Witness(E),F[1])
Again, we can check that this is conformal to the BHK interpretation, which says that a
proof of 'E & F' is a pair made of a proof of 'E' and a proof of 'F'. We do it first in
a less formal language than the language of strong terms. Assume that 'p' proves 'E'
and that 'q' proves 'F'. Then, it is easy to verify that the following is a proof of 'E
& F':
(y:Omega) |-> (r:W(?x:W(E) (F => y))) |-> r(p)(q)
i.e. of E & F := ?y:Omega ?r:W(?x:W(E) F => y) y. Conversely, assume that 'p' is a
proof of 'E & F'. Then, 'p(E)' is a proof of '?r:W(?x:W(E) (F => E)) E'. Now, since
s := (x:W(E)) |-> (y:W(F)) |-> x
is a proof of '?x:W(E) (F => E)', we see that 'p(E)(s)' is a proof of 'E'. Similarly,
'p(F)' is a proof of '?r:W(?x:W(E) (F => F)) F'. Since,
t := (x:W(E)) |-> (y:W(F)) |-> y
is a proof of '?x:W(E) (F => F)', we see that 'p(F)(t)' is a proof of 'F'.
All the above may be rewritten in the language of strong terms (this is an exercice).
Next, following Leibnitz, we define the equality like this:
equals(a,b) :=
forall(_Functional(T,_Omega),implies(app(s(0),a),app(s(0),b)))
This definition just says that 'a' is equal to 'b' if and only if any property of 'a'
is also a property of 'b'. Despite its apparently asymmetric aspect, this definition is
actually symmetric.
Finally, we have to define 'exists_unique'. This is done as follows:
exists_unique(T,E) :=
exists(T,and(E,forall(T,implies(E,equals(s(0),s(1))))))
*** Dependant conjunction and implication.
It is possible to define a dependant conjunction and a dependant implication. This will
give a meaning to 'E & F' and 'E => F' in the case where 'E:Omega/G' and 'F:Omega/[W(E)
. G]', i.e. when 'F' depends on a witness of 'E'. This situation is common in
mathematics and in the natural language.
We have already seen the rule for non dependant implication:
E:_Omega/G, F:_Omega/G
-------------------------------------------------
implies(E,F) := forall(_Witness(E),F[1]):_Omega/G
The rule for dependant implication is the following:
E:_Omega/G, F:_Omega/[_Witness(E) . G]
--------------------------------------------------
dep_implies(E,F) := forall(_Witness(E),F):_Omega/G
The difference is just that 'F' being meaningful in the context '[_Witness(E) . G]', it
should not be shifted.
The same thing works for the conjunction. Just use 'exists' instead of 'forall':
E:_Omega/G, F:_Omega/[_Witness(E) . G]
----------------------------------------------
dep_and(E,F) := exists(_Witness(E),F):_Omega/G
*** The disjunction and the negation.
The disjunction (logical 'OR') is never dependant. It is defined as follows in a less
formal language:
E | F := ?q:Omega ((E => q) => ((F => q) => q))
Again, this is the constructive variant of the well known De Morgan's law:
'E | F = ~(~E & ~F)'.
E:_Omega/G, F:_Omega/G
-------------------------------------------------------------
or(E,F) := forall(_Omega,
implies(implies(E[1],s(0)),
implies(implies(F,s(0))),s(0))):_Omega/G
The negation '~E'of 'E' is just 'E => false':
E:_Omega/G
----------------------------
neg(E) := implies(E,false)/G
*** Handling ambiguities and errors.
Because of the possibility of overloading the symbols, and the presence of type
parameters, expressions may be ambiguous. There are two kinds of ambiguity:
- simple ambiguity: a symbol may have several definitions,
- parametric ambiguity: an expression may depend on an unknown type.
In order to handle these ambiguities, we must be able to manipulate:
- meta-disjunctions of strong items,
- unknowns
For example, if the symbol x has three definitions D_1, D_2, and D_3, its
interpretation will be the meta-disjunction:
D_1 | D_2 | D_3
Later, the unification may lead to eliminate some possibilities in this
meta-disjunction.
Type unknowns are created each time we use a schema. If for example the symbol x has a
definition depending on a parameter $T, we create a new unknown, say $567, and use as a
possible interpretation of x the result of replacing the parameter $T by the unknown
$567 in this definition.
We also introduce a special element ``none'' representing the impossibility to
interpret a weak expression. Notice the analogy between:
this and this
----------------------------------
none false
meta-disjunction or
unknowns there exists
Also remark that 'false', 'or' and 'exists' are the three usual ``additive'' connectors
in logic. Of course, all this is not a hazard.
So, we have to consider a notion somewhat weaker than a strong type, and similarly a
notion somewhat weaker than a strong term. These notions have the same definitions as
strong types and strong terms, except than they include the concepts of 'none', and
'unknown' for types, and of 'none' and 'meta-disjunction' for terms. Since these
notions are precursors of strong items, we will call them ``pre-strong'' items.
public type PreStrongTerm:...
public type PreStrongType:
_None,
_Unknown (Int32),
_Parameter (String name),
_Defined (Int32 type_id,
List(PreStrongType) operands),
_Product (List(PreStrongType)),
_Functional (PreStrongType source,
PreStrongType target),
_Omega,
_Witness (PreStrongTerm statement),
_Quantified (String parameter,
PreStrongType).
public type PreStrongTerm:
none,
meta_or (PreStrongTerm, PreStrongTerm),
symbol (Int32 depth),
tuple (List(PreStrongTerm)),
proj (Int32,PreStrongTerm),
incl (PreStrongType, Int32, PreStrongTerm),
cond (PreStrongType, PreStrongTerm test, List(PreStrongTerm) cases),
lambda (PreStrongType, PreStrongTerm),
app (PreStrongTerm f, PreStrongTerm a),
forall (PreStrongType, PreStrongTerm),
description (PreStrongTerm),
property (PreStrongTerm),
choice (PreStrongTerm),
parametric (String parameter, PreStrongTerm),
parametric_app (PreStrongTerm, PreStrongType).