OCamlテクニック/monad

OCamlでモナドを楽しむ †

HaskellのMaybeモナドとかListモナドによるバックトラックとかは大変有用。 でも欲張ってモナドそのものをOCamlに導入しようとすると、色々と複雑になってくる。 そこで、camlp4を使ったモナド拡張を利用して、シンプルにモナドを楽しんでみる。

まずは環境作り †

monad拡張をダウンロードしてきたら、おもむろにmake。その後、

$ocaml -I +camlp4
     Objective Caml version 3.09.3
#load "camlp4o.cma";;
     Camlp4 Parsing version 3.09.3
#load "pa_monad.cmo";;

として準備OK

Maybeモナド †

まず定義。超簡単。

module MaybeM = struct
    let bind m f =
      match m with
        None -> None
      | Some v -> f v
  end;;
module MaybeM :
  sig val bind : 'a option -> ('a -> 'b option) -> 'b option end

使ってみる。performというのがmonad拡張のキーワード。 bind関数を呼び出してくれる。

# let env key =
    try
      Some (Sys.getenv key)
    with
      _ -> None
  in
  let name =
    perform with module MaybeM in
    user <-- env "USER"; 
    host <-- env "HOST";
    Some (user ^ "@" ^ host)
  in
  match name with
    None -> "None\n"
  | Some n -> n ^ "\n";;
- : string = "ogasawara@blendy\n"

これでoption型も怖くない。

Listモナド &dagger;

Haskellのlistモナドと同等・そのまんま。

# module ListM = struct
    let return x = [x]  
    let bind m f =
     List.flatten (List.map f m)  
    let guard c =
      if c then
        return ()
      else
        []
  end;;
module ListM :
  sig
    val return : 'a -> 'a list
    val bind : 'a list -> ('a -> 'b list) -> 'b list
    val guard : bool -> unit list
  end 

バックトラックしてくれる。

# perform with module ListM in
    i <-- [1; 2; 3];
    j <-- [4; 5; 6];
    ListM.guard (i + j > 7);
    ListM.return (i, j);;
- : (int * int) list = [(2, 6); (3, 5); (3, 6)]

応用すると、OCamlには参照型もあるので、条件に合う中で最大のものとかも簡単に作れる。

  • 私には、このほうがMonadが馴染み深く感じて好きです。ガリグ先生の授業でSEND+MORE=MONEYが出たとき、これを知っていたら・・・。それにしても、また Oleg氏ですか、化け物ですね。 彼の Native delimited continuations in (byte-code) OCaml も気になります。OCamlで(限定)継続ができるんだそうで。 -- げんま? 2007-02-02 (金) 21:57:53
  • すげええぇぇぇ。わくわくしますね。 -- しもむら? 2007-02-03 (土) 01:26:43
  • Oleg氏すごいですよねー。まだ使ったことは無いのですが、継続もそのうち試してみたいです。 -- ogasawara? 2007-02-03 (土) 04:38:55
  • reddit.programming経由. A Monad Tutorial for Ocaml -- げんま? 2007-08-13 (月) 20:19:09

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2008-06-13 (金) 00:26:14 (5790d)