第7回

課題1

レジュメで言われてることをやるだけ。

「(e1 e2)」関数適用時に環境を拡張する際、引数名に「(eval env e2)」を対応させる代わりに「(Thunk (e2 env))」を対応付ける。

あ、パターンマッチを実装してる人はそこでも変数自体を評価するタイミングがあることを忘れずに。

で、変数自体の評価の際に取り出した「(Thunk (expr env))」を用いて評価値を「(eval env expr)」とすればいい。

次のテストケースが通ればいいはず。もちろん、本家OCamlインタプリタではこれらの式を評価すると止まらなくなります。

(6/14 パターンマッチのテストケースを追加)

   1 let f = (fun x -> (fun y -> x)) in let rec loop x = loop x in f true (loop 0);;
   2  - : bool = true
   3 let f = (fun x -> (fun y -> y)) in let rec loop x = loop x in f (loop 0) true;;
   4  - : bool = true
   5 let rec loop x = loop x in (fun x -> match x with y -> 1) (loop 0);;
   6  - : int = 1
   7 
   8 (* タプルを実装した人へ *)
   9 let rec loop x = loop x in match ((3,loop 0),loop 0) with ((x,_),_) -> x;; (* IS2009Wikiより例を勝手に拝借したうえちょっと書き換え。 *)
  10  - : int = 3

課題7

載せていいのか微妙な気もしますが、EXISTモジュールの定義は下の通り。

   1 module EXIST: functor (T : sig type 'a t end) ->
   2 sig
   3         type t
   4         type 'b u = {f : 'a. 'a T.t -> 'b}
   5         val pack : 'a T.t -> t
   6         val unpack : t -> 'b u -> 'b
   7 end = 
   8 functor (T : sig type 'a t end) ->
   9 struct
  10         type 'b u = {f: 'a. 'a T.t -> 'b}
  11         type t = {t: 'false_t. 'false_t u -> 'false_t}
  12         let rec pack (x: 'a T.t) = {t = fun x1 -> x1.f x}
  13         let rec unpack x f = x.t f
  14 end;;

これを使って、unfoldやらheadやらを作っていくわけですが、作った関数は多分下のように使います。(無限長の素数を作っています。)

   1 # let rec find_prime n = (* n以上の最小の素数を返す *)
   2           let rec check_prime n i =
   3                   if n mod i = 0 then false
   4                   else if n < i * i then true
   5                   else check_prime n (i + 1) in
   6           if check_prime n 2 then n
   7           else find_prime (n + 1);;
   8 val find_prime : int -> int = <fun>
   9 # let primes = unfold (fun x -> Cons (x, find_prime (x + 1))) 2;; (* 2という数を始点として無限長の長さの素数列を作る *)
  10 val primes : stream = <abstr>
  11 # head primes;; (* primesは[2;3;5;7;11;13;・・・]のようになっているはず。リストの先頭から順に見ていく *)
  12 - : int = 2
  13 # head (tail primes);;
  14 - : int = 3
  15 # head (tail (tail primes));;                                          
  16 - : int = 5
  17 # head (tail (tail (tail primes)));;                                   
  18 - : int = 7
  19 # head (tail (tail (tail (tail primes))));;                            
  20 - : int = 11
  21 # head (tail (tail (tail (tail (tail primes)))));;                     
  22 - : int = 13
  23 # head (tail (tail (tail (tail (tail (tail primes))))));;              
  24 - : int = 17
  25 # head (tail (tail (tail (tail (tail (tail (tail primes)))))));;       
  26 - : int = 19
  27 # head (tail (tail (tail (tail (tail (tail (tail (tail primes))))))));;
  28 - : int = 23

また、レジュメにはありませんでしたが、streamに値を追加する機能もつけてきてほしいらしいです。

   1 let cons data (ls : stream) = …;;
   2 let ls = unfold …;;
   3 let ls = cons 1 ls;;
   4 head ls;; (* この式の結果が1となればいい。 *)


Categoryノート

関数・論理型プログラミング実験/課題メモ/第7回 (最終更新日時 2011-06-14 01:48:22 更新者 TakuyaKuwahara)