手習いはまだまだ続きます。
Exercise 4
問題
Exercise4 以下の関数 curry は,与えられた関数をカリー化する関数である.
この逆,つまり (2引数の)カリー化関数を受け取り,二つ組を受け取る関数に 変換する uncurry 関数を定義せよ.
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));;