次の型をもつ関数を定義せよ.
'a * ('b, 'c) sum -> ('a * 'b, 'a * 'c) sum
let f1 (x, y) = match y with Left n -> Left (x, n) | Right n -> Right (x, n);;
('a, 'b) sum * ('c, 'd) sum -> (('a * 'c, 'b * 'd) sum, ('a * 'd, 'b * 'c) sum) sum
let f2 (x, y) = match (x, y) with (Left n, Left m) -> Left (Left (n, m)) | (Left n, Right m) -> Right (Left (n, m)) | (Right n, Left m) -> Right (Right (n, m)) | (Right n, Right m) -> Left (Right (n, m));;
('a -> 'b) * ('c -> 'b) -> ('a, 'c) sum -> 'b
let f3 (x, y) = function Left m -> x m | Right m -> y m;;
(('a, 'b) sum -> 'c) -> ('a -> 'c) * ('b -> 'c)
let f4 f = (fun x -> f(Left x), fun y -> f(Right y));;
('a -> 'b, 'a -> 'c) sum -> ('a -> ('b,'c) sum)
let f5 = function Left l -> (fun x -> Left (l x)) | Right r -> (fun x -> Right (r x));;
ただし,
type ('a, 'b) sum = Left of 'a | Right of 'b;;
(('a, 'b) sum -> 'c) -> ('a -> 'c) * ('b -> 'c)
# type ('a, 'b) sum = Left of 'a | Right of 'b;; type ('a, 'b) sum = Left of 'a | Right of 'b # let f4 f = (fun x -> f(Left x), fun y -> f(Right y));; val f4 : (('a, 'b) sum -> 'c) -> 'a -> 'c * ('b -> 'c) = <fun>
テキスト3.2.3によると,* は -> より強く結合するとあるので,
val f4 : (('a, 'b) sum -> 'c) -> ('a -> 'c) * ('b -> 'c) = <fun>
こうでないと意図している型を意味しないのでは?
??pretty-printerのバグ?それとも?
ガリグ先生曰く,
","の方がより強く結合するので,
このf4の定義がそもそも課題の指定する型になっていない.
すなわち,現行のf4の定義は次のものと同じ事になっている
_ _ # let f4 f = (fun x -> ( f(Left x), fun y -> f(Right y) ));; val f4 : (('a, 'b) sum -> 'c) -> 'a -> 'c * ('b -> 'c) = <fun>
課題の要件を満たすようにするためには, 次のようにfun x -> ...を括弧でくくる必要がある.
_ _ # let f4' f = ((fun x -> f(Left x)), fun y -> f(Right y));; val f4' : (('a, 'b) sum -> 'c) -> ('a -> 'c) * ('b -> 'c) = <fun>