ピエールの綱渡り
すごいHaskellたのしく学ぼう! にMaybeモナドの説明で、次のようなものがあります。
ピエールがバランス棒を持って綱渡りしている最中、バランス棒の左右に鳥がとまる。
左右の鳥の数の差が3より大きくなったらピエールは落下して綱渡りが失敗する。
左右の鳥の数の差が3以下のままで最後までいけたら成功。
ということで、F#のコンピュテーション式で書いてみました。Maybeを表すだけだと物足りないので、以下のことをやってみました。
- コンピュテーション式のBuilerに失敗していないことを判定する関数を渡せるようにする
- let!ではなくdo!で書きつつ次の計算式に状態を渡せるようにする
利用部分を書くとこんな感じです。綱渡りを3回やっています。1回目は成功、2回目は左右の鳥の差が3を超えて失敗、3回目はバナナの皮に滑って失敗、という結果です。
let guard n = fun (left, right) -> abs(left - right) < n let tightrope = relay (guard 4) let routine = tightrope { do! landLeft 1 do! landRight 2 do! landLeft 3 } let routine2 = tightrope { do! landLeft 1 do! landRight 2 do! landLeft 5 } let routine3 = tightrope { do! landLeft 1 do! landRight 2 do! banana do! landLeft 3 } let print = function | Some(left, right) -> printfn "成功: %d, %d" left right | _ -> printfn "失敗" do exec routine (Some (0, 0)) |> print (* 成功: 4, 2 *) exec routine2 (Some (0, 0)) |> print (* 失敗 *) exec routine3 (Some (0, 0)) |> print (* 失敗 *)
シンプルに書けました!
コンピュテーション式には可能性を感じる!
Builderを書くのも読むのもしんどいけど。使う分には楽ですね。
コード全体はgistにあります。