あまりHaskellに慣れてないのでCoq使ったんですが、CoqではMonad則を証明する必要があるので、実は寧ろ説明に適していました。
HaskellだとMonad則がなぜ必要なのか示すのが面倒そう(任意の関数、なんてのはQuickCheckでも作れ無さそうな気がする)ですが、CoqではそもそもMonad則を満たすことを示さないと、Monadを使えません。
サンプルコードでは、
- Maybeモナド、Listモナドについて示してあります。
- サザエさんの家族構成を用いて、MaybeやListのサンプルコードを書いています。
Class Monad (M:Type -> Type):Type := { return' : forall {A}, A -> M A; bind : forall {A B}, M A -> (A -> M B) -> M B; left_unit : forall A B (a:A)(f:A -> M B), bind (return' a) f = f a; right_unit : forall A (ma:M A), bind ma return' = ma; assoc : forall A B C (ma:M A)(f:A -> M B) (g:B -> M C), bind (bind ma f ) g = bind ma (fun a => bind (f a) g) }. Notation "m >>= f" := (bind m f) (left associativity, at level 49). Notation "'do' a <- e ; c" := (e >>= (fun a => c)) (at level 59, right associativity). Instance Maybe : Monad option := { return' A a := Some a; bind A B ma f := match ma with | None => None | Some a => f a end }. Proof. intros; auto. intros; destruct ma; auto. intros; destruct ma; [destruct (f a)|]; auto. Defined. Eval compute in (Some 1 >>= (fun x => return' (x + 1))). Eval compute in (None >>= (fun x => return' (x + 1))). Inductive Isono:Set := Namihei | Fune | Masuo | Sazae | Katsuo | Wakame | Tara. Definition father(x:Isono):option Isono := match x with | Tara => Some Masuo | Sazae | Katsuo | Wakame => Some Namihei | _ => None end. Definition mother(x:Isono):option Isono := match x with | Tara => Some Sazae | Sazae | Katsuo | Wakame => Some Fune | _ => None end. Definition f_of_m(s:Isono):option Isono := match (mother s) with | None => None | Some x => father x end. Definition f_of_m'(s:Isono):option Isono := do x <- mother s; father x. Eval compute in (f_of_m' Tara). Eval compute in (f_of_m' Katsuo). Require Import List. Lemma flat_map_app : forall (A B:Type)(xs ys:list A)(f:A -> list B), flat_map f (xs++ys) = flat_map f xs ++ flat_map f ys. Proof. induction xs. simpl. auto. simpl. intros. erewrite IHxs. erewrite app_ass. auto. Qed. Instance List : Monad list := { return' A x := x :: nil; bind A B m f := flat_map f m }. Proof. (* left_unit *) intros A B a f. simpl. erewrite <- app_nil_end. auto. (* right_unit *) intros A m. induction m. simpl. auto. simpl. rewrite IHm. auto. (* assoc *) intros A B C m f g. induction m. simpl. auto. simpl. rewrite <- IHm. erewrite flat_map_app. auto. Defined. Definition children(x:Isono):list Isono := match x with | Namihei | Fune => Sazae::Katsuo::Wakame::nil | Sazae | Masuo => Tara::nil | _ => nil end. Eval compute in (children Fune). Eval compute in (children Katsuo). Definition grandchildren(x:Isono):list Isono := do y <- children x; children y. Eval compute in (grandchildren Fune). Eval compute in (grandchildren Katsuo).
No comments:
Post a Comment