OCamlのモナドで虫食い算

30分プログラム、その385。OCamlモナドを試してみる。ocaml-nagoya的には、一年以上前の話題な気がするけど。
http://www.itpl.co.jp/ocaml-nagoya/?OCaml%A5%C6%A5%AF%A5%CB%A5%C3%A5%AF%2Fmonadを参考にして、pa_monadコンパイルする。要するにダウンロードして、makeするだけ。

解く対象の虫食い算は、虫食い算 - Wikipediaに載っていたやつ。

□7□6□×7=3□29□6

pa_monadの何がすごいって、Monadを使えるようにperformを追加するだけじゃなくて、tuareg-modeをperformに対応させるパッチもついてくることだと思う。

使い方

# #use "musi.ml";;
# solve ();;
- : (int * int) list = [(47568, 332976)]

ソースコード

#load "camlp4o.cma";;
#load "pa_monad.cmo";;

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

let rec range a b =
  if a = b then
    []
  else
    a::range (a+1) b

let make =
  List.fold_left (fun x y -> x*10 + y) 0

let solve () =
  perform with module ListM in
    a <-- range 1 10;
    b <-- range 0 10;
    c <-- range 0 10;
    d <-- range 0 10;
    e <-- range 0 10;
    let x = make [a;7;b;6;c] in
    let y = make [3;d;2;9;e;6] in
      ListM.guard (x * 7 = y);
      ListM.return (x,y)