コンストラクタ list0_nil と list0_cons で作られるリストに対する関数テンプレートを使った一般的な実装を以前紹介しました。 ここでは、コンストラクタ list_nil と list_cons で作られるリストに対する関数テンプレートを次のように実装します。 この実装によってこれらのテンプレートにより正確な型を割り当てることができます。
この章のコード全体とテストのための追加コードは オンライン から入手できます。
型 T と整数 I1 と I2 があり、2つのリスト xs と ys が型 list(T, I1) と list(T, I2) で与えられた時、list_append(xs, ys) は xs と ys を連結した型 list(T,I1+I2) のリストを返します:
list_append のこの実装が末尾再帰でないことは明確です。型 T と整数 I1 と I2 があり、2つのリスト xs と ys が型 list(T, I1) と list(T, I2) で与えられた時、list_reverse_append(xs, ys) は xs と ys を逆順にして連結した型 list(T, I1+I2) のリストを返します:
list_reverse_append のこの実装が末尾再帰であることは明確です。リスト xs が与えられた時、list_reverse(xs) は xs の逆順を返します。 この返値は xs と同じ長さになります:
型 T1, T2 と整数 I があり、型 list(T1, I) のリスト xs と型 T1 -<cloref1> T2 のクロージャ関数 f が与えられた時、list_map(xs) は型 list(T2, I) のリスト ys を返します:
ys のそれぞれの要素 y は、xs の対応する要素を x とすれば f(x) に等しいことになります。 list_map のこの実装が末尾再帰でないことは明確です。型 T1, T2 と整数 I があり、型 list(T1, I) と list(T2, I) のリスト xs と ys がそれぞれ与えられた時、list_zip(xs, ys) は型 list((T1,T2), I) のリスト zs を返します。
zs のそれぞれの要素 z は、xs と ys の対応する要素をそれぞれ x と y とすれば、ペア (x, y) に等しいことになります。list_zip のこの実装が末尾再帰でないことは明確です。型 T1, T2, T3 と整数 I があり、2つのリスト xs と ys がそれぞれ型 list(T1, I) と list(T2, I) で、クロージャ関数 f が型 (T1, T2) -<cloref1> T3 で与えられた時、list_zipwith(xs, ys, f) は型 list(T3, I) のリスト zs を返します:
fun{ a,b:t@ype }{c:t@ype } list_zipwith {n:nat} .<n>. ( xs: list (a, n) , ys: list (b, n) , f: (a, b) -<cloref1> c ) : list (c, n) = ( case+ (xs, ys) of | ( list_nil() , list_nil() ) => list_nil((*void*)) | ( list_cons(x, xs) , list_cons(y, ys) ) => list_cons(f(x, y), list_zipwith<a,b><c>(xs, ys, f)) // end of (list_cons, list_cons) ) (* end of [list_zipwith] *)