-> a (-) :: a -> a -> a (*) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a fromInteger :: Integer -> a 「数っぽいもの」を表すNumクラスは、以下の値や関数を持つような型の抽象を表し ます。 + , - , * の演算子 negate , abs , signum の関数 fromInteger の変換関数 そして、Integer型やFloat型は、Numクラスに属することを宣言(インスタンス化)する と、それらの型をNumクラスとして抽象的に扱えるようになります。 6
) 任意の に対して、 が成り立つ が定義されている組のことです。[1] Haskellでは以下のように定義します。 -- Monoid型クラスの定義(説明用。現実のGHCのものとはちょっと違うので注意) class Monoid a where (<>) :: a -> a -> a -- 「くっつける」演算 mempty :: a -- 「くっつけても何も起こらない値」 しかし、足りないものがあると思いませんか? 8
(* くっつける演算 op *) op : A -> A -> A; (* 単位元 e *) e : A; (* 「opが結合的である」という約束 *) monoid_assoc : forall x y z, op x (op y z) = op (op x y) z; (* 「eが単位元」という約束 *) monoid_e_left : forall x, op e x = x; monoid_e_right : forall x, op x e = x }. 12
op := xorb; (* 単位元はfalse *) e := false; (* XORは結合的という約束を与える(標準ライブラリで証明済み) *) monoid_assoc := fun a b c => eq_sym (xorb_assoc a b c); (* falseは単位元という約束を与える(標準ライブラリで証明済み) *) monoid_e_left := xorb_false_l; monoid_e_right := xorb_false_r }. boolのXOR演算はモノイドの性質を満たすので、それらをモノイドのインスタンスと して扱えるようになります。 13
(M : Monoid A) : Type := { group_inv : forall x, exists xi, op xi x = e /\ op x xi = e; }. ここでは、モノイドを拡張して群を定義してみました。モノイドの諸性質に加え、逆 源に関する公理を追加することで群を定義します。 14
: forall e', (forall x, op e' x = x) -> e' = e. Proof. move=> e' H1. rewrite -(monoid_e_right e'). by rewrite -{2}(H1 e). Qed. monoid_e_right ( が単位元という約束)を使っているのが見えます。 16
A) (G : Group M) : forall x, exists! xi, op xi x = e /\ op x xi = e. Proof. move=> x. rewrite -(unique_existence _). split. - case (group_inv x) => xi [Hxil Hxir]. exists xi. by split. - move=> a b [Hal Har] [Hbl Hbr]. rewrite -(monoid_e_right a) -Hbr. rewrite monoid_assoc. by rewrite Hal monoid_e_left. Qed. group_inv (逆元が存在するという約束)、 monoid_assoc (演算が結合的という約束)な ど、様々な約束を用いて証明しているのがわかります。 17
(G : Group M) : A -> A := fun x => proj1_sig (constructive_definite_description _ (group_exists_unique_inv G x)). Lemma inv_sort A (M : Monoid A) (G : Group M) : forall x xi, xi = inv G x <-> op xi x = e /\ op x xi = e. Proof. move=> x xi. unfold inv. move: (constructive_definite_description _ (group_exists_unique_inv G x)) => He. split. - case (proj2_sig He) => [Hel Her] ->. by split. - move => Hxe. move: (group_exists_unique_inv G x). rewrite -unique_existence => [[_ Huniq]]. apply Huniq => //. by apply (proj2_sig He). Qed. Lemma op_inv_left A (M : Monoid A) (G : Group M) : forall x, op (inv G x) x = e. Proof. move=> x. by apply (inv_sort G x (inv G x)). Qed. Lemma op_inv_right A (M : Monoid A) (G : Group M) : forall x, op x (inv G x) = e. Proof. move=> x. by apply (inv_sort G x (inv G x)). Qed. 18