プログラミング言語 Standard ML 入門 (問題の解答例)
3 MLの型システム

3.3 明示的な型宣言

問 3.7

以下の関数の型を推定せよ.

  1. 1.

    fun f x y z = x y z : int

  2. 2.

    fun f x y z = x (y z) : int

  3. 3.

    fun f x y z = (x y z) : int

  4. 4.

    fun f x y z = x y (z : int)

  5. 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の考察から理解されるように,明示的な型宣 言を使用しなくても型の制約を加えることができる場合がある. 型変数を含まない型τを持つ式expτが与えられているとする.

  1. 1.

    τより一般的な多相型を持つ式expが与えられたとき, その式の動作を変えずに,その式の型をτ制限する式の定義を与えよ.

  2. 2.

    恒等関数と同一の動作をし,かつ型がτ -> τであ る関数を定義せよ.

解答例 

  1. 1.

    簡単には,
    if true then exp else Eτ とすればよい. if分を使わずに,より純粋なラムダ式で表現したければ,以下の手順で構築できる. 式expの型を式Eτの型と強制的に一致させるには,それら二つの式 を,それらの型が等式で結ばれるような式の中に埋め込めばよい.以下はその典 型的な例である.
    (fn y => fn z => z (y Eτ) (y exp)) この関数はexpと同一の動作をせず,要求を満さない. 求める式は,評価するとexpが得られるような式でなければならない. そこで,上記のexpの部分を引数とし,
    (fn x => ... (fn y =>fn z => z (y Eτ) (y exp)) ... ) exp と変形することを考える. 関数の本体全体はxと同一の意味をもつ式である必要がある. そこで,val K = fn x => fn y => xを使い,型を一致させるだ けに導入した上記の部分を捨て,exp自身を返すようにすればよい. 以下が要求を満す式の例である.
    (fn x => K x (fn y =>fn z => z (y E<sub>τ</sub>) (y exp))) exp

  2. 2.

    上記を応用すれば,以下のような例が考えられる.
    fn x => K x (fn y =>fn z => z (y Eτ) (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]