リストモナドの定義
Haskellのモナドを定義してみることを考える。まず、モナドに必要なのは以下の三つの性質である。
- f(return(A),g) = g(A)
- f(A,return) = A
- f(f(A, g),h) = f(A, (x -> f(g(B), h)))
- return
- f(a,b) = b(a)
次にリストのモナドインスタンスを定義してみる。Class MyMonad (M: Type -> Type) := { myreturn : forall {A}, A -> M A ; mybind : forall {A B}, M A -> (A -> M B) -> M B ; myleft_identify : forall A B (a: A) (f: A -> M B), mybind (myreturn a) f = f a ; myright_identify : forall A (m: M A), mybind m myreturn = m ; myassociativity : forall A B C (m:M A) (f: A -> M B) (g: B -> M C), mybind (mybind m f) g = mybind m (fun x => mybind(f x) g) }.
さて、ここまでは通ったけど、証明ができないな。。。Instance MList: MyMonad list := { myreturn A x := x :: nil ; mybind A B m f := mymap A B f m }.
mybindのところにhaskellのconcat関数見たいのがあれば行けそうだ!
証明
モナド則とリストモナドを定義したが、証明がうまくいかなかった。。。 そこで良い方法がないかと検索していたらflat_mapなる関数を見つけた。これを使ってリストモナドの定義と証明をしてみる。 まずはモナドの定義の再掲とリストモナドの再定義。
早速証明開始。Class MyMonad (M: Type -> Type) := { myreturn : forall {A}, A -> M A ; mybind : forall {A B}, M A -> (A -> M B) -> M B ; myleft_identify : forall A B (a: A) (f: A -> M B), mybind (myreturn a) f = f a ; myright_identify : forall A (m: M A), mybind m myreturn = m ; myassociativity : forall A B C (m:M A) (f: A -> M B) (g: B -> M C), mybind (mybind m f) g = mybind m (fun x => mybind(f x) g) }. Instance MList: MyMonad list := { myreturn A x := x :: nil ; mybind A B m f := flat_map f m }.
Proof. intros A B a f. simpl. ------------------------------------ 3 subgoal A : Type B : Type a : A f : A -> list B ______________________________________(1/3) f a ++ nil = f a ______________________________________(2/3) forall (A : Type) (m : list A), flat_map (fun x : A => x :: nil) m = m ______________________________________(3/3) forall (A B C : Type) (m : list A) (f : A -> list B) (g : B -> list C), flat_map g (flat_map f m) = flat_map (fun x : A => flat_map g (f x)) m
ん?simpl.しても変わらない。
まだ証明されていないのか?
とりあえず、 リストモナドの前に証明しよう!
帰納法でさくっと証明完了。 さて、戻ってリストモナドの証明の続きをしよう。Lemma nil_app : forall (A : Type)(a : list A), a ++ nil = a. Proof. intros. induction a. simpl. reflexivity. simpl. rewrite IHa. reflexivity. Qed.
んー。rewrite nil_app. reflexivity. intros. induction m. simpl. reflexivity. simpl. rewrite IHm. reflexivity. intros. induction m. simpl. reflexivity. simpl. rewrite <- IHm. --------------------------------- 1 subgoals A : Type B : Type C : Type a : A m : list A f : A -> list B g : B -> list C IHm : flat_map g (flat_map f m) = flat_map (fun x : A => flat_map g (f x)) m ______________________________________(1/1) flat_map g (f a ++ flat_map f m) = flat_map g (f a) ++ flat_map g (flat_map f m)
良い感じで進んでたけど、また詰まったな。
リストモナドの前に戻って、flat_map f (a ++ b) = flat_map f(a) ++ flat_map f (b)の
証明をしよう!
これも帰納法でさくっとできた。 よし!後は最後の大詰めだ!Lemma flat_map_app : forall (A B : Type)(l l' : list A)(f : A -> list B), flat_map f (l++l') = flat_map f l ++ flat_map f l'. Proof. induction l. simpl. intros. reflexivity. intros. simpl. rewrite IHl. rewrite app_ass. reflexivity. Qed.
やった!rewrite flat_map_app. reflexivity. Qed.
できた!