3.3 明示的な型宣言
問 3.7
以下の関数の型を推定せよ.
-
1.
fun f x y z = x y z : int
-
2.
fun f x y z = x (y z) : int
-
3.
fun f x y z = (x y z) : int
-
4.
fun f x y z = x y (z : int)
-
5.
fun f x y z = x (y z : int)
解答例 たとえばSML#の推論結果以下の通りである.
# fun f x y z = x y z : int; val f = fn : [’a,’b.(’a -> ’b -> int) -> ’a -> ’b -> int] # fun f x y z = x (y z) : int; val f = fn : [’a .(’a -> int) -> [’b .(’b -> ’a) -> ’b -> int]] # fun f x y z = (x y z) : int; val f = fn : [’a,’b.(’a -> ’b -> int) -> ’a -> ’b -> int] # fun f x y z = x y (z : int); val f = fn : [’a,’b.(’a -> int -> ’b) -> ’a -> int -> ’b] # fun f x y z = x (y z : int); val f = fn : [’a .(int -> ’a) -> [’b .(’b -> int) -> ’b -> ’a]]
問 3.8
関数fun f x = K x (fn y => x (x 1)) の動作と型を説明せよ. ただし K は問3.5で定義した関数である.
解答例 Kは2番目の引数を捨てて1番目の引数を返す関数であるから, fun f x = K x (fn y => x (x 1)) はxを受け取りxを返す関数である. 従って,xの型をAとすると,fの型は A -> Aである. ただし,(fn y => x (x 1))があるため xの型はint -> intに制限される. そこで,fの型は(int -> int) -> int -> intとなる.
実際SML#は以下のような型を推論する.
# fun f x = K x (fn y => x (x 1)); val f = fn : (int -> int) -> int -> int
問 3.9
問3.8の考察から理解されるように,明示的な型宣 言を使用しなくても型の制約を加えることができる場合がある. 型変数を含まない型を持つ式が与えられているとする.
-
1.
より一般的な多相型を持つ式が与えられたとき, その式の動作を変えずに,その式の型を制限する式の定義を与えよ.
-
2.
恒等関数と同一の動作をし,かつ型が -> であ る関数を定義せよ.
解答例
-
1.
簡単には,
if true then exp else とすればよい. if分を使わずに,より純粋なラムダ式で表現したければ,以下の手順で構築できる. 式の型を式の型と強制的に一致させるには,それら二つの式 を,それらの型が等式で結ばれるような式の中に埋め込めばよい.以下はその典 型的な例である.
(fn y => fn z => z (y ) (y )) この関数はと同一の動作をせず,要求を満さない. 求める式は,評価するとが得られるような式でなければならない. そこで,上記のの部分を引数とし,
(fn x => ... (fn y =>fn z => z (y ) (y )) ... ) と変形することを考える. 関数の本体全体はxと同一の意味をもつ式である必要がある. そこで,val K = fn x => fn y => xを使い,型を一致させるだ けに導入した上記の部分を捨て,自身を返すようにすればよい. 以下が要求を満す式の例である.
(fn x => K x (fn y =>fn z => z (y E<sub>τ</sub>) (y exp))) exp -
2.
上記を応用すれば,以下のような例が考えられる.
fn x => K x (fn y =>fn z => z (y ) (y x)) たとえば,fn x => K x (fn y =>fn z => z (y 1) (y x))¿は int -> int型の関数である.
問 3.10
higherTwice と同一の動作をし型が等しい関数を,明示的な型制約 を加えずに定義せよ.
解答例 以下にコード例とSML#で推論された型を示す。
# fun higherTwice f x = f (f (K x (fn y => (y x, y id)))); val higherTwice = fn : [’a .((’a -> ’a) -> ’a -> ’a) -> (’a -> ’a) -> ’a -> ’a]