-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSubtyping_J.v
More file actions
2269 lines (1928 loc) · 94.3 KB
/
Subtyping_J.v
File metadata and controls
2269 lines (1928 loc) · 94.3 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
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
(** * Subtyping_J :サブタイプ *)
(* * Subtyping *)
(* $Date: 2011-05-07 21:28:52 -0400 (Sat, 07 May 2011) $ *)
Require Export MoreStlc_J.
(* ###################################################### *)
(* * Concepts *)
(** * 概念 *)
(* We now turn to the study of _subtyping_, perhaps the most
characteristic feature of the static type systems used by many
recently designed programming languages. *)
(** さて、サブタイプ(_subtyping_)の学習に入ります。
サブタイプはおそらく、近年設計されたプログラミング言語で使われる静的型システムの最も特徴的な機能です。
*)
(* ###################################################### *)
(* ** A Motivating Example *)
(** ** 動機付けのための例 *)
(* In the simply typed lamdba-calculus with records, the term
<<
(\r:{y:Nat}. (r.y)+1) {x=10,y=11}
>>
is not typable: it involves an application of a function that wants
a one-field record to an argument that actually provides two
fields, while the [T_App] rule demands that the domain type of the
function being applied must match the type of the argument
precisely.
But this is silly: we're passing the function a _better_ argument
than it needs! The only thing the body of the function can
possibly do with its record argument [r] is project the field [y]
from it: nothing else is allowed by the type. So the presence or
absence of an extra [x] field should make no difference at all.
So, intuitively, it seems that this function should be applicable
to any record value that has at least a [y] field.
Looking at the same thing from another point of view, a record with
more fields is "at least as good in any context" as one with just a
subset of these fields, in the sense that any value belonging to
the longer record type can be used _safely_ in any context
expecting the shorter record type. If the context expects
something with the shorter type but we actually give it something
with the longer type, nothing bad will happen (formally, the
program will not get stuck).
The general principle at work here is called _subtyping_. We say
that "[S] is a subtype of [T]", informally written [S <: T], if a
value of type [S] can safely be used in any context where a value
of type [T] is expected. The idea of subtyping applies not only to
records, but to all of the type constructors in the language --
functions, pairs, etc. *)
(** レコードを持つ単純型付きラムダ計算では、項
<<
(\r:{y:Nat}. (r.y)+1) {x=10,y=11}
>>
は型付けできません。なぜなら、
これはフィールドが1つのレコードを引数としてとる関数に2つのフィールドを持つレコードが与えられている部分を含んでいて、
一方、[T_App]規則は関数の定義域の型は引数の型に完全に一致することを要求するからです。
しかしこれは馬鹿らしいことです。
実際には関数に、必要とされるものより良い引数を与えているのです!
この関数の本体がレコード引数[r]に対して行うことができることはおそらく、
そのフィールド[y]を射影することだけです。型から許されることは他にはありません。
すると、他に[x]フィールドが存在するか否かは何の違いもないはずです。
これから、直観的に、
この関数は少なくとも[y]フィールドは持つ任意のレコード値に適用可能であるべきと思われます。
同じことを別の観点から見ると、より豊かなフィールドを持つレコードは、
そのサブセットのフィールドだけを持つレコードと
「任意のコンテキストで少なくとも同等の良さである」と言えるでしょう。
より長い(多いフィールドを持つ)レコード型の任意の値は、
より短かいレコード型が求められるコンテキストで「安全に」(_safely_)使えるという意味においてです。
コンテキストがより短かい型のものを求めているときに、より長い型のものを与えた場合、
何も悪いことは起こらないでしょう(形式的には、プログラムは行き詰まることはないでしょう)。
ここではたらいている一般原理はサブタイプ(付け)(_subtyping_)と呼ばれます。
型[T]の値が求められている任意のコンテキストで型[S]の値が安全に使えるとき、
「[S]は[T]のサブタイプである」と言い、非形式的に [S <: T] と書きます。
サブタイプの概念はレコードだけではなく、関数、対、など言語のすべての型コンストラクタに適用されます。
*)
(* ** Subtyping and Object-Oriented Languages *)
(** ** サブタイプとオブジェクト指向言語 *)
(* Subtyping plays a fundamental role in many programming
languages -- in particular, it is closely related to the notion of
_subclassing_ in object-oriented languages.
An _object_ (in Java, C[#], etc.) can be thought of as a record,
some of whose fields are functions ("methods") and some of whose
fields are data values ("fields" or "instance variables").
Invoking a method [m] of an object [o] on some arguments [a1..an]
consists of projecting out the [m] field of [o] and applying it to
[a1..an].
The type of an object can be given as either a _class_ or an
_interface_. Both of these provide a description of which methods
and which data fields the object offers.
Classes and interfaces are related by the _subclass_ and
_subinterface_ relations. An object belonging to a subclass (or
subinterface) is required to provide all the methods and fields of
one belonging to a superclass (or superinterface), plus possibly
some more.
The fact that an object from a subclass (or sub-interface) can be
used in place of one from a superclass (or super-interface) provides
a degree of flexibility that is is extremely handy for organizing
complex libraries. For example, a graphical user interface
toolkit like Java's Swing framework might define an abstract
interface [Component] that collects together the common fields and
methods of all objects having a graphical representation that can
be displayed on the screen and that can interact with the user.
Examples of such object would include the buttons, checkboxes, and
scrollbars of a typical GUI. A method that relies only on this
common interface can now be applied to any of these objects.
Of course, real object-oriented languages include many other
features besides these. Fields can be updated. Fields and
methods can be declared [private]. Classes also give _code_ that
is used when constructing objects and implementing their methods,
and the code in subclasses cooperate with code in superclasses via
_inheritance_. Classes can have static methods and fields,
initializers, etc., etc.
To keep things simple here, we won't deal with any of these
issues -- in fact, we won't even talk any more about objects or
classes. (There is a lot of discussion in Types and Programming
Languages, if you are interested.) Instead, we'll study the core
concepts behind the subclass / subinterface relation in the
simplified setting of the STLC. *)
(** サブタイプは多くのプログラミング言語で重要な役割を演じます。
特に、オブジェクト指向言語のサブクラス(_subclassing_)の概念と近い関係にあります。
(JavaやC[#]等の)オブジェクトはレコードと考えることができます。
いくつかのフィールドは関数(「メソッド」)で、いくつかのフィールドはデータ値
(「フィールド」または「インスタンス変数」)です。
オブジェクト[o]のメソッド[m]を引数[a1..an]のもとで呼ぶことは、
[o]から[m]フィールドを射影として抽出して、それを[a1..an]に適用することです。
オブジェクトの型はクラス(_class_)またはインターフェース(_interface_)
として与えることができます。
この両者はどちらも、どのメソッドとどのデータフィールドをオブジェクトが提供するかを記述します。
クラスやインターフェースは、サブクラス(_subclass_)関係やサブインターフェース
(_subinterface_)関係で関係づけられます。
サブクラス(またはサブインターフェース)に属するオブジェクトには、スーパークラス
(またはスーパーインターフェース)
に属するオブジェクトのメソッドとフィールドのすべての提供することが求められ、
おそらくそれに加えてさらにいくつかのものを提供します。
サブクラス(またはサブインターフェース)のオブジェクトをスーパークラス(またはスーパーインターフェース)
のオブジェクトの場所で使えるという事実は、
複雑なライブラリの構築にきわめて便利なほどの柔軟性を提供します。
例えば、Javaの Swing
フレームワークのようなグラフィカルユーザーインターフェースツールキットは、
スクリーンに表示できユーザとインタラクションできるグラフィカルな表現を持つすべてのオブジェクトに共通のフィールドとメソッドを集めた、抽象インターフェース[Component]を定義するでしょう。
そのようなオブジェクトの例としては、典型的なGUIのボタン、チェックボックス、スクロールバーなどがあります。
この共通インターフェースのみに依存するメソッドは任意のそれらのオブジェクトに適用できます。
もちろん、実際のオブジェクト指向言語はこれらに加えてたくさんの他の機能を持っています。
フィールドは更新できます。フィールドとメソッドは[private]と宣言できます。
クラスはまた、
オブジェクトを構成しそのメソッドをインプリメントするのに使われる「コード」を与えます。
そしてサブクラスのコードは「継承」を通じてスーパークラスのコードと協調します。
クラスは、静的なメソッドやフィールド、イニシャライザ、等々を持つことができます。
ものごとを単純なまま進めるために、これらの問題を扱うことはしません。
実際、これ以上オブジェクトやクラスについて話すことはありません。
(もし興味があるなら、 Types and Programming Languages にたくさんの議論があります。)
その代わり、STLCの単純化された設定のもとで、
サブクラス/サブインターフェース関係の背後にある核となる概念について学習します。 *)
(* ** The Subsumption Rule *)
(** ** 包摂規則 *)
(* Our goal for this chapter is to add subtyping to the simply typed
lambda-calculus (with products). This involves two steps:
- Defining a binary _subtype relation_ between types.
- Enriching the typing relation to take subtyping into account.
The second step is actually very simple. We add just a single rule
to the typing relation -- the so-called _rule of subsumption_:
[[[
Gamma |- t : S S <: T
------------------------- (T_Sub)
Gamma |- t : T
]]]
This rule says, intuitively, that we can "forget" some of the
information that we know about a term. *)
(** この章のゴールは(直積を持つ)単純型付きラムダ計算にサブタイプを追加することです。
これは2つのステップから成ります:
- 型の間の二項サブタイプ関係(_subtype relation_)を定義します。
- 型付け関係をサブタイプを考慮した形に拡張します。
2つ目のステップは実際はとても単純です。型付け関係にただ1つの規則だけを追加します。
その規則は、包摂規則(_rule of subsumption_)と呼ばれます:
[[
Gamma |- t : S S <: T
------------------------- (T_Sub)
Gamma |- t : T
]]
この規則は、直観的には、項について知っている情報のいくらかを「忘れる」ことができると言っています。 *)
(* For example, we may know that [t] is a record with two
fields (e.g., [S = {x:A->A, y:B->B}]], but choose to forget about
one of the fields ([T = {y:B->B}]) so that we can pass [t] to a
function that expects just a single-field record. *)
(** 例えば、[t]が2つのフィールドを持つレコード(例えば、[S = {x:A->A, y:B->B}])で、
フィールドの1つを忘れることにした([T = {y:B->B}])とします。
すると[t]を、1フィールドのレコードを引数としてとる関数に渡すことができるようになります。 *)
(* ** The Subtype Relation *)
(** ** サブタイプ関係 *)
(* The first step -- the definition of the relation [S <: T] -- is
where all the action is. Let's look at each of the clauses of its
definition. *)
(** 最初のステップ、関係 [S <: T] の定義にすべてのアクションがあります。
定義のそれぞれを見てみましょう。 *)
(* *** Products *)
(** *** 直積型 *)
(** 最初に、直積型です。ある一つの対が他の対より「良い」とは、
それぞれの成分が他の対の対応するものより良いことです。
[[
S1 <: T1 S2 <: T2
-------------------- (S_Prod)
S1*S2 <: T1*T2
]]
*)
(* *** Arrows *)
(** *** 関数型 *)
(* Suppose we have two functions [f] and [g] with these types:
<<
f : C -> {x:A,y:B}
g : (C->{y:B}) -> D
>>
That is, [f] is a function that yields a record of type
[{x:A,y:B}], and [g] is a higher-order function that expects
its (function) argument to yield a record of type [{y:B}]. (And
suppose, even though we haven't yet discussed subtyping for
records, that [{x:A,y:B}] is a subtype of [{y:B}]) Then the
application [g f] is safe even though their types do not match up
precisely, because the only thing [g] can do with [f] is to apply
it to some argument (of type [C]); the result will actually be a
two-field record, while [g] will be expecting only a record with a
single field, but this is safe because the only thing [g] can then
do is to project out the single field that it knows about, and
this will certainly be among the two fields that are present.
This example suggests that the subtyping rule for arrow types
should say that two arrow types are in the subtype relation if
their results are:
[[[
S2 <: T2
---------------- (S_Arrow2)
S1->S2 <: S1->T2
]]]
We can generalize this to allow the arguments of the two arrow
types to be in the subtype relation as well:
[[[
T1 <: S1 S2 <: T2
-------------------- (S_Arrow)
S1->S2 <: T1->T2
]]]
Notice, here, that the argument types are subtypes "the other way
round": in order to conclude that [S1->S2] to be a subtype of
[T1->T2], it must be the case that [T1] is a subtype of [S1]. The
arrow constructor is said to be _contravariant_ in its first
argument and _covariant_ in its second.
The intuition is that, if we have a function [f] of type [S1->S2],
then we know that [f] accepts elements of type [S1]; clearly, [f]
will also accept elements of any subtype [T1] of [S1]. The type of
[f] also tells us that it returns elements of type [S2]; we can
also view these results belonging to any supertype [T2] of
[S2]. That is, any function [f] of type [S1->S2] can also be viewed
as having type [T1->T2]. *)
(** 次の型を持つ2つの関数[f]と[g]があるとします:
<<
f : C -> {x:A,y:B}
g : (C->{y:B}) -> D
>>
つまり、[f]は型[{x:A,y:B}]のレコードを引数とする関数であり、
[g]は引数として、型[{y:B}]のレコードを引数とする関数をとる高階関数です。
(そして、レコードのサブタイプについてはまだ議論していませんが、
[{x:A,y:B}] は [{y:B}] のサブタイプであるとします。)
すると、関数適用 [g f] は、両者の型が正確に一致しないにもかかわらず安全です。
なぜなら、[g]が[f]について行うことができるのは、
[f]を(型[C]の)ある引数に適用することだけだからです。
その結果は実際には2フィールドのレコードになります。
ここで[g]が期待するのは1つのフィールドを持つレコードだけです。
しかしこれは安全です。なぜなら[g]がすることができるのは、
わかっている1つのフィールドを射影することだけで、
それは存在する2つのフィールドの1つだからです。
この例から、関数型のサブタイプ規則が以下のようになるべきということが導かれます。
2つの関数型がサブタイプ関係にあるのは、その結果が次の条件のときです:
[[
S2 <: T2
---------------- (S_Arrow2)
S1->S2 <: S1->T2
]]
これを一般化して、2つの関数型のサブタイプ関係を、引数の条件を含めた形にすることが、同様にできます:
[[
T1 <: S1 S2 <: T2
-------------------- (S_Arrow)
S1->S2 <: T1->T2
]]
ここで注意するのは、引数の型はサブタイプ関係が逆向きになることです。
[S1->S2] が [T1->T2] のサブタイプであると結論するためには、
[T1]が[S1]のサブタイプでなければなりません。
関数型のコンストラクタは最初の引数について反変(_contravariant_)であり、
二番目の引数について共変(_covariant_)であると言います。
直観的には、型[S1->S2]の関数[f]があるとき、[f]は型[S1]の要素を引数にとることがわかります。
明らかに[f]は[S1]の任意のサブタイプ[T1]の要素をとることもできます。
[f]の型は同時に[f]が型[S2]の要素を返すことも示しています。
この値が[S2]の任意のスーパータイプ[T2]に属することも見ることができます。
つまり、型[S1->S2]の任意の関数[f]は、型[T1->T2]を持つと見ることもできるということです。 *)
(* *** Top *)
(** *** Top *)
(* It is natural to give the subtype relation a maximal element -- a
type that lies above every other type and is inhabited by
all (well-typed) values. We do this by adding to the language one
new type constant, called [Top], together with a subtyping rule
that places it above every other type in the subtype relation:
[[[
-------- (S_Top)
S <: Top
]]]
The [Top] type is an analog of the [Object] type in Java and C[#]. *)
(** サブタイプ関係の最大要素を定めることは自然です。他のすべての型のスーパータイプであり、
すべての(型付けできる)値が属する型です。このために言語に新しい一つの型定数[Top]を追加し、
[Top]をサブタイプ関係の他のすべての型のスーパータイプとするサブタイプ規則を定めます:
[[
-------- (S_Top)
S <: Top
]]
[Top]型はJavaやC[#]における[Object]型に対応するものです。 *)
(* *** Structural Rules *)
(** *** 構造規則 *)
(* To finish off the subtype relation, we add two "structural rules"
that are independent of any particular type constructor: a rule of
_transitivity_, which says intuitively that, if [S] is better than
[U] and [U] is better than [T], then [S] is better than [T]...
[[[
S <: U U <: T
---------------- (S_Trans)
S <: T
]]]
... and a rule of _reflexivity_, since any type [T] is always just
as good as itself:
[[[
------ (S_Refl)
T <: T
]]]
*)
(** サブタイプ関係の最後に、2つの「構造規則」("structural rules")を追加します。
これらは特定の型コンストラクタからは独立したものです。
推移律(rule of _transitivity_)は、直観的には、
[S]が[U]よりも良く、[U]が[T]よりも良ければ、[S]は[T]よりも良いというものです...
[[
S <: U U <: T
---------------- (S_Trans)
S <: T
]]
... そして反射律(rule of _reflexivity_)は、
任意の型はそれ自身と同じ良さを持つというものです。
[[
------ (S_Refl)
T <: T
]]
*)
(* *** Records *)
(** *** レコード *)
(* What about subtyping for record types?
The basic intuition about subtyping for record types is that it is
always safe to use a "bigger" record in place of a "smaller" one.
That is, given a record type, adding extra fields will always
result in a subtype. If some code is expecting a record with
fields [x] and [y], it is perfectly safe for it to receive a record
with fields [x], [y], and [z]; the [z] field will simply be ignored.
For example,
<<
{x:Nat,y:Bool} <: {x:Nat}
{x:Nat} <: {}
>>
This is known as "width subtyping" for records.
We can also create a subtype of a record type by replacing the type
of one of its fields with a subtype. If some code is expecting a
record with a field [x] of type [T], it will be happy with a record
having a field [x] of type [S] as long as [S] is a subtype of
[T]. For example,
<<
{a:{x:Nat}} <: {a:{}}
>>
This is known as "depth subtyping".
Finally, although the fields of a record type are written in a
particular order, the order does not really matter. For example,
<<
{x:Nat,y:Bool} <: {y:Bool,x:Nat}
>>
This is known as "permutation subtyping".
We could try formalizing these requirements in a single subtyping
rule for records as follows:
[[[
for each jk in j1..jn,
exists ip in i1..im, such that
jk=ip and Sp <: Tk
---------------------------------- (S_Rcd)
{i1:S1...im:Sm} <: {j1:T1...jn:Tn}
]]]
That is, the record on the left should have all the field labels of
the one on the right (and possibly more), while the types of the
common fields should be in the subtype relation. However, This rule
is rather heavy and hard to read. If we like, we can decompose it
into three simpler rules, which can be combined using [S_Trans] to
achieve all the same effects.
First, adding fields to the end of a record type gives a subtype:
[[[
n > m
--------------------------------- (S_RcdWidth)
{i1:T1...in:Tn} <: {i1:T1...im:Tm}
]]]
We can use [S_RcdWidth] to drop later fields of a multi-field
record while keeping earlier fields, showing for example that
[{y:B, x:A} <: {y:B}].
Second, we can apply subtyping inside the components of a compound
record type:
[[[
S1 <: T1 ... Sn <: Tn
---------------------------------- (S_RcdDepth)
{i1:S1...in:Sn} <: {i1:T1...in:Tn}
]]]
For example, we can use [S_RcdDepth] and [S_RcdWidth] together to
show that [{y:{z:B}, x:A} <: {y:{}}].
Third, we need to be able to reorder fields. The example we
originally had in mind was [{x:A,y:B} <: {y:B}]. We
haven't quite achieved this yet: using just [S_RcdDepth] and
[S_RcdWidth] we can only drop fields from the _end_ of a record
type. So we need:
[[[
{i1:S1...in:Sn} is a permutation of {i1:T1...in:Tn}
--------------------------------------------------- (S_RcdPerm)
{i1:S1...in:Sn} <: {i1:T1...in:Tn}
]]]
Further examples:
- [{x:A,y:B}] <: [{y:B,x:A}].
- [{}->{j:A} <: {k:B}->Top]
- [Top->{k:A,j:B} <: C->{j:B}]
*)
(** レコード型のサブタイプは何でしょうか?
レコード型のサブタイプについての基本的直観は、
「より小さな」レコードの場所で「より大きな」レコードを使うことは常に安全だということです。
つまり、レコード型があるとき、さらにフィールドを追加したものは常にサブタイプになるということです。
もしあるコードがフィールド[x]と[y]を持つレコードを期待していたとき、
レコード[x]、[y]、[z]を持つレコードを受けとることは完璧に安全です。
[z]フィールドは単に無視されるだけでしょう。
例えば次の通りです。
<<
{x:Nat,y:Bool} <: {x:Nat}
{x:Nat} <: {}
>>
これはレコードの"width subtyping"(幅サブタイプ)として知られます。
レコードの1つのフィールドの型をそのサブタイプで置き換えることでも、
レコードのサブタイプを作ることができます。
もしあるコードが型[T]のフィールド[x]を持つレコードを待っていたとき、
型[S]が型[T]のサブタイプである限りは、
型[S]のフィールド[x]を持つレコードが来ることはハッピーです。
例えば次の通りです。
<<
{a:{x:Nat}} <: {a:{}}
>>
これは"depth subtyping"(深さサブタイプ)として知られています。
最後に、レコードのフィールドは特定の順番で記述されますが、その順番は実際には問題ではありません。
例えば次の通りです。
<<
{x:Nat,y:Bool} <: {y:Bool,x:Nat}
>>
これは"permutation subtyping"(順列サブタイプ)として知られています。
これらをレコードについての単一のサブタイプ規則に形式化することをやってみましょう。
次の通りです:
[[
for each jk in j1..jn,
exists ip in i1..im, such that
jk=ip and Sp <: Tk
---------------------------------- (S_Rcd)
{i1:S1...im:Sm} <: {j1:T1...jn:Tn}
]]
つまり、左のレコードは(少なくとも)右のレコードのフィールドラベルをすべて持ち、
両者で共通するフィールドはサブタイプ関係になければならない、ということです。
しかしながら、この規則はかなり重くて読むのがたいへんです。
ここでは、3つのより簡単な規則に分解します。この3つは[S_Trans]を使うことで結合することができ、
同じ作用をすることができます。
最初に、レコード型の最後にフィールドを追加したものはサブタイプになります:
[[
n > m
--------------------------------- (S_RcdWidth)
{i1:T1...in:Tn} <: {i1:T1...im:Tm}
]]
[S_RcdWidth]を使うと、複数のフィールドを持つレコードについて、
前方のフィールドを残したまま後方のフィールドを落とすことができます。
この規則で例えば [{y:B, x:A} <: {y:B}] が示されます。
二つ目に、レコード型の構成要素の内部にサブタイプ規則を適用できます:
[[
S1 <: T1 ... Sn <: Tn
---------------------------------- (S_RcdDepth)
{i1:S1...in:Sn} <: {i1:T1...in:Tn}
]]
例えば [S_RcdDepth]と[S_RcdWidth]を両方使って [{y:{z:B}, x:A} <: {y:{}}]
を示すことができます。
三つ目に、フィールドの並べ替えを可能にする必要があります。
念頭に置いてきた例は [{x:A,y:B} <: {y:B}] でした。
これはまだ達成されていませんでした。
[S_RcdDepth]と[S_RcdWidth]だけでは、レコード型の「後」からフィールドを落とすことしかできません。
これから次の規則が必要です:
[[
{i1:S1...in:Sn} is a permutation of {i1:T1...in:Tn}
--------------------------------------------------- (S_RcdPerm)
{i1:S1...in:Sn} <: {i1:T1...in:Tn}
]]
さらなる例です:
- [{x:A,y:B}] <: [{y:B,x:A}].
- [{}->{j:A} <: {k:B}->Top]
- [Top->{k:A,j:B} <: C->{j:B}]
*)
(* It is worth noting that real languages may choose not to adopt
all of these subtyping rules. For example, in Java:
- A subclass may not change the argument or result types of a
method of its superclass (i.e., no depth subtyping or no arrow
subtyping, depending how you look at it).
- Each class has just one superclass ("single inheritance" of
classes)
- Each class member (field or method) can be assigned a single
index, adding new indices "on the right" as more members are
added in subclasses (i.e., no permutation for classes)
- A class may implement multiple interfaces -- so-called "multiple
inheritance" of interfaces (i.e., permutation is allowed for
interfaces). *)
(** なお、実際の言語ではこれらのサブタイプ規則のすべてを採用しているとは限らないことは、
注記しておくべきでしょう。例えばJavaでは:
- サブクラスではスーパークラスのメソッドの引数または結果の型を変えることはできません
(つまり、depth subtypingまたは関数型サブタイプのいずれかができないということです。
どちらかは見方によります)。
- それぞれのクラスは(直上の)スーパークラスを1つだけ持ちます(クラスの「単一継承」
("single inheritance")です)。
- 各クラスのメンバー(フィールドまたはメソッド)は1つだけインデックスを持ち、
サブクラスでメンバーが追加されるたびに新しいインデックスが「右に」追加されます
(つまり、クラスには並び換えがありません)。
- クラスは複数のインターフェースをインプリメントできます。これは
インターフェースの「多重継承」("multiple inheritance")と呼ばれます
(つまり、インターフェースには並び換えがあります)。 *)
(* *** Records, via Products and Top (optional) *)
(** *** 直積と Top によるレコード (optional) *)
(* Exactly how we formalize all this depends on how we are choosing
to formalize records and their types. If we are treating them as
part of the core language, then we need to write down subtyping
rules for them. The file [RecordSub.v] shows how this extension
works.
On the other hand, if we are treating them as a derived form that
is desugared in the parser, then we shouldn't need any new rules:
we should just check that the existing rules for subtyping product
and [Unit] types give rise to reasonable rules for record
subtyping via this encoding. To do this, we just need to make one
small change to the encoding described earlier: instead of using
[Unit] as the base case in the encoding of tuples and the "don't
care" placeholder in the encoding of records, we use [Top]. So:
<<
{a:Nat, b:Nat} ----> {Nat,Nat} i.e. (Nat,(Nat,Top))
{c:Nat, a:Nat} ----> {Nat,Top,Nat} i.e. (Nat,(Top,(Nat,Top)))
>>
The encoding of record values doesn't change at all. It is
easy (and instructive) to check that the subtyping rules above are
validated by the encoding. For the rest of this chapter, we'll
follow this approach. *)
(** これらすべてをどのように形式化するかは、レコードとその型をどのように形式化するかに、
まさに依存しています。もしこれらを核言語の一部として扱うならば、
そのためのサブタイプ規則を書き下す必要があります。
ファイル[RecordSub_J.v]で、この拡張がどのようにはたらくかを示します。
一方、もしそれらをパーサで展開される派生形として扱うならば、新しい規則は何も必要ありません。
直積と[Unit]型のサブタイプについての既存の規則が、
このエンコードによるレコードのサブタイプに関する妥当な規則になっているかをチェックすれば良いだけです。
このために、前述のエンコードをわずかに変更する必要があります。
組のエンコードのベースケースおよびレコードのエンコードの "don't care" プレースホルダとして、
[Unit]の代わりに[Top]を使います。
すると:
<<
{a:Nat, b:Nat} ----> {Nat,Nat} つまり (Nat,(Nat,Top))
{c:Nat, a:Nat} ----> {Nat,Top,Nat} つまり (Nat,(Top,(Nat,Top)))
>>
レコード値のエンコードは何も変更しません。
このエンコードで上述のサブタイプ規則が成立することをチェックするのは容易です
(そしてタメになります)。この章の残りでは、このアプローチを追求します。 *)
(* ###################################################### *)
(* * Core definitions *)
(** * 中核部の定義 *)
(* We've already sketched the significant extensions that we'll need
to make to the STLC: (1) add the subtype relation and (2) extend
the typing relation with the rule of subsumption. To make
everything work smoothly, we'll also implement some technical
improvements to the presentation from the last chapter. The rest
of the definitions -- in particular, the syntax and operational
semantics of the language -- are identical to what we saw in the
last chapter. Let's first do the identical bits. *)
(** STLCに必要となる重要な拡張を既に概観してきました:
(1)サブタイプ関係を追加し、(2)型関係に包摂規則を拡張することです。
すべてがスムースにいくように、前の章の表現にいくらかの技術的改善を行います。
定義の残りは -- 特に言語の構文と操作的意味は -- 前の章で見たものと同じです。
最初に同じ部分をやってみましょう。 *)
(* ################################### *)
(* *** Syntax *)
(** *** 構文 *)
(* Just for the sake of more interesting examples, we'll make one
more very small extension to the pure STLC: an arbitrary set of
additional _base types_ like [String], [Person], [Window], etc.
We won't bother adding any constants belonging to these types or
any operators on them, but we could easily do so. *)
(** よりおもしろい例のために、純粋STLCに非常に小さな拡張を行います。
[String]、[Person]、[Window]等のような、任意の「基本型」の集合を追加します。
これらの型の定数を追加したり、その型の上の操作を追加したりすることをわざわざやりませんが、
そうすることは簡単です。 *)
(* In the rest of the chapter, we formalize just base types,
booleans, arrow types, [Unit], and [Top], leaving product types as
an exercise. *)
(** この章の残りでは、基本型、ブール型、関数型、[Unit]と[Top]のみ形式化し、
直積型は練習問題にします。 *)
Inductive ty : Type :=
| ty_Top : ty
| ty_Bool : ty
| ty_base : id -> ty
| ty_arrow : ty -> ty -> ty
| ty_Unit : ty
.
Tactic Notation "ty_cases" tactic(first) ident(c) :=
first;
[ Case_aux c "ty_Top" | Case_aux c "ty_Bool"
| Case_aux c "ty_base" | Case_aux c "ty_arrow"
| Case_aux c "ty_Unit" |
].
Inductive tm : Type :=
| tm_var : id -> tm
| tm_app : tm -> tm -> tm
| tm_abs : id -> ty -> tm -> tm
| tm_true : tm
| tm_false : tm
| tm_if : tm -> tm -> tm -> tm
| tm_unit : tm
.
Tactic Notation "tm_cases" tactic(first) ident(c) :=
first;
[ Case_aux c "tm_var" | Case_aux c "tm_app"
| Case_aux c "tm_abs" | Case_aux c "tm_true"
| Case_aux c "tm_false" | Case_aux c "tm_if"
| Case_aux c "tm_unit"
].
(* ################################### *)
(* *** Substitution *)
(** *** 包摂 *)
(* The definition of substitution remains the same as for the
ordinary STLC. *)
(** 包摂の定義は、いつものSTLCと同様です。 *)
Fixpoint subst (s:tm) (x:id) (t:tm) : tm :=
match t with
| tm_var y =>
if beq_id x y then s else t
| tm_abs y T t1 =>
tm_abs y T (if beq_id x y then t1 else (subst s x t1))
| tm_app t1 t2 =>
tm_app (subst s x t1) (subst s x t2)
| tm_true =>
tm_true
| tm_false =>
tm_false
| tm_if t1 t2 t3 =>
tm_if (subst s x t1) (subst s x t2) (subst s x t3)
| tm_unit =>
tm_unit
end.
(* ################################### *)
(* *** Reduction *)
(** *** 簡約 *)
(* Likewise the definitions of the [value] property and the [step]
relation. *)
(** [value](値)の定義や[step]関係の定義と同様です。 *)
Inductive value : tm -> Prop :=
| v_abs : forall x T t,
value (tm_abs x T t)
| t_true :
value tm_true
| t_false :
value tm_false
| v_unit :
value tm_unit
.
Hint Constructors value.
Reserved Notation "t1 '==>' t2" (at level 40).
Inductive step : tm -> tm -> Prop :=
| ST_AppAbs : forall x T t12 v2,
value v2 ->
(tm_app (tm_abs x T t12) v2) ==> (subst v2 x t12)
| ST_App1 : forall t1 t1' t2,
t1 ==> t1' ->
(tm_app t1 t2) ==> (tm_app t1' t2)
| ST_App2 : forall v1 t2 t2',
value v1 ->
t2 ==> t2' ->
(tm_app v1 t2) ==> (tm_app v1 t2')
| ST_IfTrue : forall t1 t2,
(tm_if tm_true t1 t2) ==> t1
| ST_IfFalse : forall t1 t2,
(tm_if tm_false t1 t2) ==> t2
| ST_If : forall t1 t1' t2 t3,
t1 ==> t1' ->
(tm_if t1 t2 t3) ==> (tm_if t1' t2 t3)
where "t1 '==>' t2" := (step t1 t2).
Tactic Notation "step_cases" tactic(first) ident(c) :=
first;
[ Case_aux c "ST_AppAbs" | Case_aux c "ST_App1"
| Case_aux c "ST_App2" | Case_aux c "ST_IfTrue"
| Case_aux c "ST_IfFalse" | Case_aux c "ST_If"
].
Hint Constructors step.
(* ###################################################################### *)
(* * Subtyping *)
(** * サブタイプ *)
(* Now we come to the interesting part. We begin by defining
the subtyping relation and developing some of its important
technical properties. *)
(** さて、おもしろい所にやって来ました。サブタイプ関係の定義から始め、その重要な技術的性質を調べます。 *)
(* ################################### *)
(* ** Definition *)
(** ** 定義 *)
(* The definition of subtyping is just what we sketched in the
motivating discussion. *)
(** サブタイプの定義は、動機付けの議論のところで概観した通りです。 *)
Inductive subtype : ty -> ty -> Prop :=
| S_Refl : forall T,
subtype T T
| S_Trans : forall S U T,
subtype S U ->
subtype U T ->
subtype S T
| S_Top : forall S,
subtype S ty_Top
| S_Arrow : forall S1 S2 T1 T2,
subtype T1 S1 ->
subtype S2 T2 ->
subtype (ty_arrow S1 S2) (ty_arrow T1 T2)
.
(* Note that we don't need any special rules for base types: they are
automatically subtypes of themselves (by [S_Refl]) and [Top] (by
[S_Top]), and that's all we want. *)
(** なお、基本型については特別な規則は何ら必要ありません。
基本型は自動的に([S_Refl]より)自分自身のサブタイプであり、
([S_Top]より)[Top]のサブタイプでもあります。そしてこれが必要な全てです。 *)
Hint Constructors subtype.
Tactic Notation "subtype_cases" tactic(first) ident(c) :=
first;
[ Case_aux c "S_Refl" | Case_aux c "S_Trans"
| Case_aux c "S_Top" | Case_aux c "S_Arrow"
].
(* ############################################### *)
(* ** Subtyping Examples and Exercises *)
(** ** サブタイプの例と練習問題 *)
Module Examples.
Notation x := (Id 0).
Notation y := (Id 1).
Notation z := (Id 2).
Notation A := (ty_base (Id 6)).
Notation B := (ty_base (Id 7)).
Notation C := (ty_base (Id 8)).
Notation String := (ty_base (Id 9)).
Notation Float := (ty_base (Id 10)).
Notation Integer := (ty_base (Id 11)).
(* **** Exercise: 2 stars, optional (subtyping judgements) *)
(** **** 練習問題: ★★, optional (subtyping judgements) *)
(* (Do this exercise after you have added product types to the
language, at least up to this point in the file).
Using the encoding of records into pairs, define pair types
representing the record types
[[
Person := { name : String }
Student := { name : String ;
gpa : Float }
Employee := { name : String ;
ssn : Integer }
]]
*)
(** (この練習問題は、少なくともファイルのここまでに、直積型を言語に追加した後で行ってください。)
レコードを対でエンコードするときに、以下のレコード型を表す直積型を定義しなさい。
[[
Person := { name : String }
Student := { name : String ;
gpa : Float }
Employee := { name : String ;
ssn : Integer }
]]
*)
Definition Person : ty :=
(* FILL IN HERE *) admit.
Definition Student : ty :=
(* FILL IN HERE *) admit.
Definition Employee : ty :=
(* FILL IN HERE *) admit.
Example sub_student_person :
subtype Student Person.
Proof.
(* FILL IN HERE *) Admitted.
Example sub_employee_person :
subtype Employee Person.
Proof.
(* FILL IN HERE *) Admitted.
(** [] *)
Example subtyping_example_0 :
subtype (ty_arrow C Person)
(ty_arrow C ty_Top).
(* C->Person <: C->Top *)
Proof.
apply S_Arrow.
apply S_Refl. auto.
Qed.
(* The following facts are mostly easy to prove in Coq. To get
full benefit from the exercises, make sure you also
understand how to prove them on paper! *)
(** 以下の事実のほとんどは、Coqで証明するのは簡単です。
練習問題の効果を十分に得るために、
どうやって証明するか自分が理解していることを紙に証明を書いて確認しなさい。 *)
(* **** Exercise: 1 star, optional (subtyping_example_1) *)
(** **** 練習問題: ★, optional (subtyping_example_1) *)
Example subtyping_example_1 :
subtype (ty_arrow ty_Top Student)
(ty_arrow (ty_arrow C C) Person).
(* Top->Student <: (C->C)->Person *)
Proof with eauto.
(* FILL IN HERE *) Admitted.
(** [] *)
(* **** Exercise: 1 star, optional (subtyping_example_2) *)
(** **** 練習問題: ★, optional (subtyping_example_2) *)
Example subtyping_example_2 :
subtype (ty_arrow ty_Top Person)
(ty_arrow Person ty_Top).
(* Top->Person <: Person->Top *)
Proof with eauto.
(* FILL IN HERE *) Admitted.
(** [] *)
End Examples.
(* **** Exercise: 1 star, optional (subtype_instances_tf_1) *)
(** **** 練習問題: ★, optional (subtype_instances_tf_1) *)
(* Suppose we have types [S], [T], [U], and [V] with [S <: T]
and [U <: V]. Which of the following subtyping assertions
are then true? Write _true_ or _false_ after each one.
(Note that [A], [B], and [C] are base types.)
- [T->S <: T->S]
- [Top->U <: S->Top]
- [(C->C) -> (A*B) <: (C->C) -> (Top*B)]
- [T->T->U <: S->S->V]
- [(T->T)->U <: (S->S)->V]
- [((T->S)->T)->U <: ((S->T)->S)->V]
- [S*V <: T*U]
[]
*)
(** 型[S]、[T]、[U]、[V]があり [S <: T] かつ [U <: V] とします。
このとき以下のサブタイプ関係の主張のうち、正しいものはどれでしょうか?
それぞれの後に「真」または「偽」と書きなさい。
(ここで、[A]、[B]、[C]は基本型とします。)
- [T->S <: T->S]
- [Top->U <: S->Top]
- [(C->C) -> (A*B) <: (C->C) -> (Top*B)]
- [T->T->U <: S->S->V]
- [(T->T)->U <: (S->S)->V]
- [((T->S)->T)->U <: ((S->T)->S)->V]
- [S*V <: T*U]
[]
*)
(* **** Exercise: 1 star (subtype_instances_tf_2) *)
(** **** 練習問題: ★ (subtype_instances_tf_2) *)
(* Which of the following statements are true? Write TRUE or FALSE
after each one.
[[
forall S T,
S <: T ->
S->S <: T->T
forall S T,
S <: A->A ->
exists T,
S = T->T /\ T <: A
forall S T1 T1,
S <: T1 -> T2 ->