練習問題 14.3 (1) 拡張リストのための max_list関数
max や map関数の拡張リストに対しての定義を、上の length、alength と同じように、差分(`App の場合のみ)を記述するように定義しなさい。
解答 (max_list関数)
まず、max関数の拡張リストに対しての定義を考えてみた。
区別のために、その関数の名前を amax_list とする。
(* サンプルのリスト *)
let l1 = `Cons (1, `Cons (2, `Nil));;
let l2 = `Cons (3, `Cons (4, `Nil));;
let l6 = `Cons (5, `App (l1, l2));;
let l7 = `Cons (10, `Cons (17, `App (l1, l2)));;
(* ふつうの max_list -- list の中の最大値を求める *)
let rec max_list = function
`Cons (x, `Nil) -> x
| `Cons (x, `Cons (y, l)) ->
if x < y then max_list (`Cons(y, l))
else max_list (`Cons(x, l));;
max_list l2;; (* - : int = 4 *)
(* `App を含まないリストのための make_max 関数
* f に max_list関数を指定すると、`App を含まないリストの最大値を求めることができる
* f に amax_list関数を指定すると、`App を含むリストの最大値を求める関数に処理を渡す
*)
let make_max f = function
`Cons (x, `Nil) -> x
| `Cons (x, `Cons (y, l)) ->
if x < y then f (`Cons(y, l))
else f (`Cons(x, l));;
(* val make_max :
([> `Cons of 'a * 'b ] -> 'a) ->
[< `Cons of 'a * [< `Cons of 'a * 'b | `Nil ] ] -> 'a = <fun>
*)
(* `App を含まないリストの最大値を求める *)
let rec max_list l = make_max max_list l;;
(*val max_list : [ `Cons of 'a * ([< `Cons of 'a * 'b | `Nil ] as 'b) ] -> 'a =
<fun> *)
max_list l2;; (* - : int = 4 *)
(* make_amax 関数のための max 関数 -- ふつうのリストの中の最大値を求める *)
let max l =
let rec max_in l e =
match l with
[] -> e
| v :: rest ->
if v > e then max_in rest v
else max_in rest e
in
max_in l 0;;
(* val max : int list -> int = <fun> *)
(* `App を含む拡張リストのための make_amax 関数
* `App を含まなければ、make_max 関数に処理をわたす
*)
let make_amax f = function
(`Cons (_, `Nil) | `Cons (_, `Cons(_, _))) as l -> make_max f l
| `Cons (x, `App (l1, l2)) ->
let a1 = f l1 and a2 = f l2 in
max [x; a1; a2];;
(* val make_amax :
(([> `Cons of int * 'b ] as 'a) -> int) ->
[< `Cons of int * [< `App of 'a * 'a | `Cons of int * 'b | `Nil ] ] -> int =
<fun> *)
(* `App を含む拡張リストの最大値を求める関数 *)
let rec amax_list l = make_amax amax_list l;;
(* val amax_list :
([ `Cons of int * ([< `App of 'a * 'a | `Cons of int * 'b | `Nil ] as 'b) ]
as 'a) ->
int = <fun> *)
amax_list l6;; (* - : int = 5 *)
amax_list l7;; (* - : int = 17 *)