@@ -3,33 +3,46 @@ import Mathlib.Topology.Instances.Real
3
3
4
4
set_option autoImplicit true
5
5
6
+ /- OMIT:
7
+ Morphisms
8
+ ---------
9
+
10
+ OMIT. -/
6
11
/- TEXT:
7
12
.. _section_hierarchies_morphisms:
8
13
9
- Morphisms
10
- ---------
14
+ 射
15
+ ---
11
16
17
+ TEXT. -/
18
+ /- OMIT:
12
19
So far in this chapter, we discussed how to create a hierarchy of mathematical structures.
13
20
But defining structures is not really completed until we have morphisms. There are two
14
21
main approaches here. The most obvious one is to define a predicate on functions.
22
+ OMIT. -/
23
+ /- TEXT:
24
+ この章ではここまで,数学的構造の階層を作る方法について述べてきました.しかし,構造を定義するには射が必要です.射の定義には2つのアプローチがあります.最も明白なのは,関数に対しての述語を定義することです.
15
25
BOTH: -/
16
26
17
27
-- QUOTE:
18
28
def isMonoidHom₁ [Monoid G] [Monoid H] (f : G → H) : Prop :=
19
29
f 1 = 1 ∧ ∀ g g', f (g * g') = f g * f g'
20
30
-- QUOTE.
21
- /- TEXT :
31
+ /- OMIT :
22
32
In this definition, it is a bit unpleasant to use a conjunction. In particular users
23
33
will need to remember the ordering we chose when they want to access the two conditions.
24
34
So we could use a structure instead.
25
35
36
+ OMIT. -/
37
+ /- TEXT:
38
+ この定義では,連言を使うことは少々好ましくありません.特に使う側にとっては,2つの条件にアクセスしたいときに条件の並び順を覚えておかなければなりません.そこで,上記の代わりに構造体を使うことができます.
26
39
BOTH: -/
27
40
-- QUOTE:
28
41
structure isMonoidHom₂ [Monoid G] [Monoid H] (f : G → H) : Prop where
29
42
map_one : f 1 = 1
30
43
map_mul : ∀ g g', f (g * g') = f g * f g'
31
44
-- QUOTE.
32
- /- TEXT :
45
+ /- OMIT :
33
46
Once we are here, it is even tempting to make it a class and use the type class instance resolution
34
47
procedure to automatically infer ``isMonoidHom₂`` for complicated functions out of instances for
35
48
simpler functions. For instance a composition of monoid morphisms is a monoid morphism and this
@@ -39,6 +52,12 @@ would be very frustrating. More generally one must always keep in mind that reco
39
52
function is applied in a given expression is a very difficult problem, called the "higher-order
40
53
unification problem". So Mathlib does not use this class approach.
41
54
55
+ OMIT. -/
56
+ /- TEXT:
57
+ ここまで来ると,上記をクラスにして,型クラスのインスタンス解決プロセスを使って,単純な関数のインスタンスから複雑な関数の ``isMonoidHom₂`` を自動的に推論できるようにしたくなるでしょう.例えばモノイドの射の合成はモノイドの射となり,これは上記クラスの有用なインスタンスのように思えるでしょう.しかし,このようなインスタンスは ``g ∘ f`` を至るところで探し出す必要があるので,解決プロセスにとっては非常に厄介です. ``g (f x)`` でさえも失敗してしまうので,使う人にとってはとてもイライラすることでしょう.より一般的には,与えられた式の中でどの関数が適用されているかを認識することは「高階ユニフィケーション問題」と呼ばれる非常に難しい問題であることを常に念頭に置く必要があります.そのため,Mathlibではこのようなクラスの使い方はされていません.
58
+
59
+ TEXT. -/
60
+ /- OMIT:
42
61
A more fundamental question is whether we use predicates as above (using either a ``def`` or a
43
62
``structure``) or use structures bundling a function and predicates. This is partly a psychological
44
63
issue. It is extremely rare to consider a function between monoids that is not a morphism.
@@ -47,16 +66,28 @@ it is a noun. On the other hand one can argue that a continuous function between
47
66
is really a function that happens to be continuous. This is one reason why Mathlib has a
48
67
``Continuous`` predicate. For instance you can write:
49
68
69
+ OMIT. -/
70
+ /- TEXT:
71
+ より根本的な問題として,上記のように述語を使うか( ``def`` か ``structure`` のどちらでも),それとも関数と述語を束ねた構造体を使うのかということです.これは気持ちの問題でもあります.射ではないモノイド間の関数を考えることは非常にまれです.「モノイドの射」は普通の関数につけられる形容詞ではなく,名詞なのです.一方で位相空間の間の連続関数は,考えていた対象の関数がたまたま連続だったと主張することもできます.これがMathlibに ``Continuous`` という述語がある理由です.例えば次のように書くことができます:
50
72
BOTH: -/
51
73
-- QUOTE:
52
74
example : Continuous (id : ℝ → ℝ) := continuous_id
53
75
-- QUOTE.
54
- /- TEXT :
76
+ /- OMIT :
55
77
We still have bundles continuous functions, which are convenient for instance to put a topology
56
78
on a space of continuous functions, but they are not the primary tool to work with continuity.
57
79
80
+ OMIT. -/
81
+ /- TEXT:
82
+ 連続関数のあつまりは,例えば連続関数の空間に位相を置くのに便利ですが,連続性を扱う主要な道具ではありません.
83
+
84
+ TEXT. -/
85
+ /- OMIT:
58
86
By contrast, morphisms between monoids (or other algebraic structures) are bundled as in:
59
87
88
+ OMIT. -/
89
+ /- TEXT:
90
+ これとは対照的に,モノイド(あるいは他の代数的構造)間の射は以下のようにまとめられます:
60
91
BOTH: -/
61
92
-- QUOTE:
62
93
@[ext]
@@ -66,13 +97,16 @@ structure MonoidHom₁ (G H : Type) [Monoid G] [Monoid H] where
66
97
map_mul : ∀ g g', toFun (g * g') = toFun g * toFun g'
67
98
68
99
-- QUOTE.
69
- /- TEXT :
100
+ /- OMIT :
70
101
Of course we don't want to type ``toFun`` everywhere so we register a coercion using
71
102
the ``CoeFun`` type class. Its first argument is the type we want to coerce to a function.
72
103
The second argument describes the target function type. In our case it is always ``G → H``
73
104
for every ``f : MonoidHom₁ G H``. We also tag ``MonoidHom₁.toFun`` with the ``coe`` attribute to
74
105
make sure it is displayed almost invisibly in the tactic state, simply by a ``↑`` prefix.
75
106
107
+ OMIT. -/
108
+ /- TEXT:
109
+ もちろん,全ての利用箇所で ``toFun`` を打ち込みたいわけではないので, ``CoeFun`` 型クラスを使って型強制を登録します.最初の引数は関数に強制したい型です.第2引数には対象となる関数の型を指定します.この場合,すべての ``f : MonoidHom₁ G H`` に対して常に ``G → H`` とします.また, ``MonoidHom₁.toFun`` には ``coe`` 属性のタグを付け, ``↑`` 接頭辞をつけるだけでタクティクモードではほとんど ``toFun`` の存在が見えないようになるようにしています.
76
110
BOTH: -/
77
111
-- QUOTE:
78
112
instance [Monoid G] [Monoid H] : CoeFun (MonoidHom₁ G H) (fun _ ↦ G → H) where
@@ -81,17 +115,23 @@ instance [Monoid G] [Monoid H] : CoeFun (MonoidHom₁ G H) (fun _ ↦ G → H) w
81
115
attribute [coe] MonoidHom₁.toFun
82
116
-- QUOTE.
83
117
84
- /- TEXT :
118
+ /- OMIT :
85
119
Let us check we can indeed apply a bundled monoid morphism to an element.
86
120
121
+ OMIT. -/
122
+ /- TEXT:
123
+ モノイドの射のあつまりを要素に適用できることを確認してみましょう.
87
124
BOTH: -/
88
125
89
126
-- QUOTE:
90
127
example [Monoid G] [Monoid H] (f : MonoidHom₁ G H) : f 1 = 1 := f.map_one
91
128
-- QUOTE.
92
- /- TEXT :
129
+ /- OMIT :
93
130
We can do the same with other kind of morphisms until we reach ring morphisms.
94
131
132
+ OMIT. -/
133
+ /- TEXT:
134
+ 他の射についても環の射についてまでは同じことができます.
95
135
BOTH: -/
96
136
97
137
-- QUOTE:
@@ -111,7 +151,7 @@ structure RingHom₁ (R S : Type) [Ring R] [Ring S] extends MonoidHom₁ R S, Ad
111
151
112
152
-- QUOTE.
113
153
114
- /- TEXT :
154
+ /- OMIT :
115
155
There are a couple of issues about this approach. A minor one is we don't quite know where to put
116
156
the ``coe`` attribute since the ``RingHom₁.toFun`` does not exist, the relevant function is
117
157
``MonoidHom₁.toFun ∘ RingHom₁.toMonoidHom₁`` which is not a declaration that can be tagged with an
@@ -124,6 +164,9 @@ a type class for objects that are at least monoid morphisms, instantiate that cl
124
164
morphisms and ring morphisms and use it to state every lemma. In the definition below,
125
165
``F`` could be ``MonoidHom₁ M N``, or ``RingHom₁ M N`` if ``M`` and ``N`` have a ring structure.
126
166
167
+ OMIT. -/
168
+ /- TEXT:
169
+ この方法にはいくつか問題があります.そのうちの些細なものとして, ``RingHom₁.toFun`` が存在しないため, ``coe`` 属性をどこに置けばいいのかよくわからないことです.対応する関数は ``MonoidHom₁.toFun ∘ RingHom₁.toMonoidHom₁`` ですが,これは属性タグを付けられる宣言ではありません.(ただ ``CoeFun (RingHom₁ R S) (fun _ ↦ R → S)`` インスタンスを定義することはできます.)もっと重要なのは,モノイドの射に関する補題は環の射には直接適用できないということです.このため,モノイドの射の補題を適用しようとするたびに, ``RingHom₁.toMonoidHom₁`` と格闘するか,環の射の補題をすべて書き直すかのどちらかしかありません.どちらの選択肢も魅力的ではないため,Mathlibはここで新しい階層の技法を使います.そのアイデアは,少なくともモノイド射であるオブジェクトのための型クラスを定義し,そのクラスをモノイドの射と環の射の両方でインスタンス化し,すべての補題を記述するために使うというものです.以下の定義では, ``F`` は ``MonoidHom₁ M N`` であり,また ``M`` と ``N`` が環構造を持つ場合は ``RingHom₁ M N`` でもあります.
127
170
BOTH: -/
128
171
129
172
-- QUOTE:
@@ -133,18 +176,21 @@ class MonoidHomClass₁ (F : Type) (M N : Type) [Monoid M] [Monoid N] where
133
176
map_mul : ∀ f g g', toFun f (g * g') = toFun f g * toFun f g'
134
177
-- QUOTE.
135
178
136
- /- TEXT :
179
+ /- OMIT :
137
180
However there is a problem with the above implementation. We haven't registered a coercion to
138
181
function instance yet. Let us try to do it now.
139
182
183
+ OMIT. -/
184
+ /- TEXT:
185
+ しかし,上記の実装には問題があります.まだ関数インスタンスへの型強制が登録されていません.これをやってみましょう.
140
186
BOTH: -/
141
187
142
188
-- QUOTE:
143
189
def badInst [Monoid M] [Monoid N] [MonoidHomClass₁ F M N] : CoeFun F (fun _ ↦ M → N) where
144
190
coe := MonoidHomClass₁.toFun
145
191
-- QUOTE.
146
192
147
- /- TEXT :
193
+ /- OMIT :
148
194
Making the an instance would be bad. When faced with something like ``f x`` where the type of ``f``
149
195
is not a function type, Lean will try to find a ``CoeFun`` instance to coerce ``f`` into a function.
150
196
The above function has type:
@@ -157,10 +203,19 @@ monoid instance in the database. If you are curious to see the effect of such an
157
203
can type ``set_option synthInstance.checkSynthOrder false in`` on top of the above declaration,
158
204
replace ``def badInst`` with ``instance``, and look for random failures in this file.
159
205
206
+ OMIT. -/
207
+ /- TEXT:
208
+ このようなインスタンスの作成はよくありません. ``f`` が関数の型ではない場合に ``f x`` という式に遭遇した時,Leanは ``f`` を関数に変換するために ``CoeFun`` インスタンスを探そうとします.上記の関数の型は ``{M N F : Type} → [Monoid M] → [Monoid N] → [MonoidHomClass₁ F M N] → CoeFun F (fun x ↦ M → N)`` となり,したがってこれを適用しようとすると,未知の型 ``M`` と ``N`` , ``F`` がどの順番で推論されるべきかLeanにとっては先験的に明らかではありません.これは前節で見た悪いインスタンスの種類とはまた少し違うものですが,同じ問題に帰着します. ``M`` のインスタンスがわからないと,Leanは未知の型のモノイドインスタンスを探さなければならず,データベース内の **すべての** モノイドインスタンスを試すことになります.このようなインスタンスの効果を見たい場合は,上記の宣言の上に ``set_option synthInstance.checkSynthOrder false in`` と入力し, ``def badInst`` を ``instance`` に置き換えると,このファイル中であちこち失敗することを確認できるでしょう.
209
+
210
+ TEXT. -/
211
+ /- OMIT:
160
212
Here the solution is easy, we need to tell Lean to first search what is ``F`` and then deduce ``M``
161
213
and ``N``. This is done using the ``outParam`` function. This function is defined as the identity
162
214
function, but is still recognized by the type class machinery and triggers the desired behavior.
163
215
Hence we can retry defining our class, paying attention to the ``outParam`` function:
216
+ OMIT. -/
217
+ /- TEXT:
218
+ この問題の解決は簡単です.まず ``F`` がなんであるかを検索し,次に ``M`` と ``N`` を推論するようにLeanに指示すればよいのです.これは ``outParam`` 関数を使って行います.この関数は恒等関数として定義されていますが,型クラスの仕組みによって認識され,目的の動作を引き起こします.したがって, ``outParam`` 関数に注意しながら,クラスの定義をやり直すことができます.
164
219
BOTH: -/
165
220
166
221
-- QUOTE:
@@ -175,9 +230,12 @@ instance [Monoid M] [Monoid N] [MonoidHomClass₂ F M N] : CoeFun F (fun _ ↦ M
175
230
attribute [coe] MonoidHomClass₂.toFun
176
231
-- QUOTE.
177
232
178
- /- TEXT :
233
+ /- OMIT :
179
234
Now we can proceed with our plan to instantiate this class.
180
235
236
+ OMIT. -/
237
+ /- TEXT:
238
+ これでこのクラスをインスタンス化する方針を進めることができます.
181
239
BOTH: -/
182
240
183
241
-- QUOTE:
@@ -192,10 +250,13 @@ instance (R S : Type) [Ring R] [Ring S] : MonoidHomClass₂ (RingHom₁ R S) R S
192
250
map_mul := fun f ↦ f.toMonoidHom₁.map_mul
193
251
-- QUOTE.
194
252
195
- /- TEXT :
253
+ /- OMIT :
196
254
As promised every lemma we prove about ``f : F`` assuming an instance of ``MonoidHomClass₁ F`` will
197
255
apply both to monoid morphisms and ring morphisms.
198
256
Let us see an example lemma and check it applies to both situations.
257
+ OMIT. -/
258
+ /- TEXT:
259
+ お約束したように, ``MonoidHomClass₁ F`` のインスタンスを仮定して, ``f : F`` について証明するすべての補題は,モノイドの射と環の射の両方に適用できます.補題の例を見て,両方の状況に当てはまることを確認してみましょう.
199
260
BOTH: -/
200
261
201
262
-- QUOTE:
@@ -211,18 +272,27 @@ map_inv_of_inv f h
211
272
212
273
-- QUOTE.
213
274
214
- /- TEXT :
275
+ /- OMIT :
215
276
At first sight, it may look like we got back to our old bad idea of making ``MonoidHom₁`` a class.
216
277
But we haven't. Everything is shifted one level of abstraction up. The type class resolution
217
278
procedure won't be looking for functions, it will be looking for either
218
279
``MonoidHom₁`` or ``RingHom₁``.
219
280
281
+ OMIT. -/
282
+ /- TEXT:
283
+ 一見すると, ``MonoidHom₁`` をクラスにするという昔の悪いアイデアに戻ったように見えるかもしれません.しかしそうではありません.すべて抽象度が1つ上がっているのです.型クラス解決プロセスは関数を探すのではなく, ``MonoidHom₁`` か ``RingHom₁`` のどちらかを探すことになります.
284
+
285
+ TEXT. -/
286
+ /- OMIT:
220
287
One remaining issue with our approach is the presence of repetitive code around the ``toFun``
221
288
field and the corresponding ``CoeFun`` instance and ``coe`` attribute. It would also be better
222
289
to record that this pattern is used only for function with extra properties, meaning that the
223
290
coercion to functions should be injective. So Mathlib adds one more layer of abstraction with
224
291
the base class ``FunLike``. Let us redefine our ``MonoidHomClass`` on top of this base layer.
225
292
293
+ OMIT. -/
294
+ /- TEXT:
295
+ 本書でのアプローチで残っている問題は, ``toFun`` フィールドとそれに対応する ``CoeFun`` インスタンスと ``coe`` 属性の周りに繰り返しコードが存在することです.また,このパターンは余分なプロパティを持つ関数にのみ使用され,関数への型強制は単射的であるべきだということを記録しておいたほうが良いでしょう.このために,Mathlibは基底クラス ``FunLike`` で抽象化のレイヤーを1つ増やしています.この基底クラスの上に ``MonoidHomClass`` を再定義してみましょう.
226
296
BOTH: -/
227
297
228
298
-- QUOTE:
@@ -238,18 +308,27 @@ instance (M N : Type) [Monoid M] [Monoid N] : MonoidHomClass₃ (MonoidHom₁ M
238
308
map_mul := MonoidHom₁.map_mul
239
309
-- QUOTE.
240
310
241
- /- TEXT :
311
+ /- OMIT :
242
312
Of course the hierarchy of morphisms does not stop here. We could go on and define a class
243
313
``RingHomClass₃`` extending ``MonoidHomClass₃`` and instantiate it on ``RingHom`` and
244
314
then later on ``AlgebraHom`` (algebras are rings with some extra structure). But we've
245
315
covered the main formalization ideas used in Mathlib for morphisms and you should be ready
246
316
to understand how morphisms are defined in Mathlib.
247
317
318
+ OMIT. -/
319
+ /- TEXT:
320
+ もちろん射の階層はここで終わりません.さらに続けて ``MonoidHomClass₃`` を特殊化した ``RingHomClass₃`` クラスを定義し,それを ``RingHom`` にインスタンス化し,さらに ``AlgebraHom`` にインスタンス化することもできます.(代数環は環に特別な構造を加えたものです.)しかし,Mathlibで使用される射の主な形式化のアイデアをカバーしたので,Mathlibで射がどのように定義されるかを理解する準備はできているはずです.
321
+
322
+ TEXT. -/
323
+ /- OMIT:
248
324
As an exercise, you should try to define your class of bundled order-preserving function between
249
325
ordered types, and then order preserving monoid morphisms. This is for training purposes only.
250
326
Like continuous functions, order preserving functions are primarily unbundled in Mathlib where
251
327
they are defined by the ``Monotone`` predicate. Of course you need to complete the class
252
328
definitions below.
329
+ OMIT. -/
330
+ /- TEXT:
331
+ 演習問題として,順序型の間の順序を保つ関数を集めたクラスと,順序を保つモノイドの射を定義してみましょう.これは練習のためだけのものです.連続関数と同様に,順序を保つ関数はMathlibではとくにまとめられておらず, ``Monotone`` 述語によって定義されています.この演習を達成するにはもちろん,以下のクラス定義を完成させる必要があります.
253
332
BOTH: -/
254
333
255
334
-- QUOTE:
0 commit comments