読者です 読者をやめる 読者になる 読者になる

YAMAGUCHI::weblog

土足で窓から失礼いたします。今日からあなたの息子になります。 当年とって92歳、下町の発明王、エジソンです。

Objective Caml 入門 手習い(4章 続き)

OCaml

手習いはまだまだ続きます。

Exercise 4

問題

Exercise4 以下の関数 curry は,与えられた関数をカリー化する関数である.
この逆,つまり (2引数の)カリー化関数を受け取り,二つ組を受け取る関数に 変換する uncurry 関数を定義せよ.

自分の答え
open Printf

(* Exercise 4 *)

let curry f x y = f (x, y);;
let average (x, y) = (x +. y) /. 2.0;;
let curried_avg = curry average;;

let uncurry f (x, y) = f x y;;

let avg = uncurry curried_avg;;

Printf.printf "avg -> %f\n" (avg (4.0, 5.3));;

Exercise 5

問題

Exercise5 以下の関数 repeat は double, fourtimes などを一般化したもので, f を n 回,x に適用する関数である.
これを使って,フィボナッチ数を計算する関数 fib を定義せよ。

自分の答え
open Printf

(* Exercise 5 *)
let rec repeat f n x =
  if n > 0 then repeat f (n-1) (f x) else x;;

let fib n =
  let (fibn, _) = repeat (fun (p, c) -> (c, c+p)) n (0, 1)
  in fibn
;;

let print_fib n =
  Printf.printf "fib %d -> %d\n" n (fib n)
;;

print_fib 5;;

おまけ

Y Combinator

Skypeで質問していたらid:camlspotterからY Combinatorを講義していただいた。

(* Y combinator *)
let f fact x = if x = 1 then 1 else fact (x - 1) * x
let rec y f x = f (y f) x
let z = y f 10;;

Printf.printf "%d\n" z;;

多少ずるしてるけどY Combinatorがこれで実装出来ているらしい。たしかに動く!なんか詐欺にあっているみたい!
ちなみにこのずるしてるというのはYをlet recで宣言しているから。これでは再帰定義になってしまうので、let recを使わないでY combinatorを実装する話はこちらを参照。

type 'a recc = In of ('a recc -> 'a);;
let out (In x) = x;;

let y f = (fun x a -> f (out x x) a) (In (fun x a -> f (out x x) a));;